1825: [JSOI2010]蔬菜庆典

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 112  Solved: 45
[Submit][Status][Discuss]

Description

Input

Output

对于每组数据,输出一行。若蔬菜的总价能无限制增大,输出"+inf"(不含引号)。否则输出一个整数,表示所有蔬菜的最大总价。

Sample Input

5
-1 3
1 2
1 1
3 2
3 2
5
-1 3
1 2
1 1
3 2
3 3
0

Sample Output

13
+inf

HINT

简化版题意:

给出一棵有根树,每个点有一个权值v,可以对一个有父亲并且又有儿子的节点选择一个儿子进行一次操作使$v[x]=v[fa[x]]+v[son[x]]-v[x]$。

问无限制使用这种操作后树上的权值和最大为多少。

参照样例,显然当某一时刻一个非根节点有两个不同权值的儿子时答案就是正无穷。

假设这个点的权值为A,父亲为B,权值小的孩子为C,大的为D。

第一次 A'=(B+C-A)  第二次 A''=B+D-A'=B+D-B-C+A=A+D-C>A

然后考虑怎么构造出这种情况。

因为根节点是不会变的,所以对于1的每一个儿子可以分开处理,设为函数solve(x)。

如果某个点有两个儿子不同那么就不需要构造直接返回inf。

如果每个点的$v[fa[x]]+v[son[x]]$都等于$2v[x]$显然这棵树的权值是固定的,返回整棵树的权值。

那么现在存在一个点$v[fa[x]]+v[son[x]]!=2[v[x]]$,这个点的权值可以变化,那么说明这棵树的非叶节点的权值都可以变化(递归考虑,一个点的权值要么本身就能变化,那么它父亲或儿子变化后它可以变化),此时如果答案不为inf,这棵树只能是一条链,或者链上的最后一个点可以有多个叶儿子。

两种情况没有区别,考虑一条链怎么做。

不妨让它长这样:

....A B C.....

对B操作,我们从两个视角看:

A:  B'=A+(C-B)

C:  B'=C-(B-A)

B'-A=(C-B)

C-B'=(B-A)

其实就是差分序列的相邻两项交换了位置。

然后做法就很明了了。。。

为了让和尽量大,我们把差分序列排个序就好啦>_<

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. #define N 200005
  6. #define int long long
  7. #define inf 0x3f3f3f3f
  8. using namespace std;
  9. int head[N],ver[N],nxt[N],tot;
  10. int son[N];
  11. void add(int a,int b)
  12. {
  13. tot++;nxt[tot]=head[a];head[a]=tot;ver[tot]=b;return ;
  14. }
  15. int n;
  16. int p[N],v[N];
  17. bool flag,lian,flag2,flag3;
  18. int sum[N],ss;
  19. void dfs(int x)
  20. {
  21. int pre=inf;
  22. if(!head[x])ss+=v[x];
  23. if(p[x]!=1&&son[x]!=0&&son[p[x]]>=2)flag3=1;
  24. for(int i=head[x];i;i=nxt[i])
  25. {
  26. if(son[x]>1)lian=1;
  27. if(pre!=inf&&v[ver[i]]!=pre)flag=1;
  28. if(v[p[x]]+v[ver[i]]!=2*v[x])flag2=1;
  29. pre=v[ver[i]];
  30. dfs(ver[i]);
  31. sum[x]+=sum[ver[i]];
  32. }
  33. sum[x]+=v[x];
  34. return ;
  35. }
  36. int st[N],top;
  37. bool cmp(int x,int y)
  38. {
  39. return x>y;
  40. }
  41. int solve(int x)
  42. {
  43. flag=0;lian=0;flag2=0;flag3=0;ss=0;
  44. dfs(x);
  45. if(flag||(lian&&flag2&&flag3))return 0;
  46. if(lian&&flag3)return sum[x];
  47. top=0;
  48. for(int i=x;;i=ver[head[i]])
  49. {
  50. st[++top]=v[i]-v[p[i]];
  51. if(!head[i])break;
  52. }
  53. sort(st+1,st+top+1,cmp);
  54. int now=v[1];
  55. int sm=0;
  56. for(int i=1;i<top;i++)
  57. {
  58. now+=st[i];
  59. sm+=now;
  60. }
  61. return sm+ss;
  62. }
  63. signed main()
  64. {
  65. while(~scanf("%lld",&n))
  66. {
  67. if(n==0)break;
  68. for(int i=1;i<=n;i++)
  69. {
  70. scanf("%lld%lld",&p[i],&v[i]);
  71. if(p[i]!=-1)add(p[i],i),son[p[i]]++;
  72. }
  73. int ans=0,ts=0;
  74. for(int i=head[1];i;i=nxt[i])
  75. {
  76. int tmp=solve(ver[i]);
  77. if(flag||(lian&&flag2&&flag3))ts=1;
  78. ans+=tmp;
  79. }
  80. if(ts)puts("+inf");
  81. else printf("%lld\n",ans+v[1]);
  82. tot=0;
  83. for(int i=1;i<=n;i++)head[i]=sum[i]=p[i]=v[i]=son[i]=0;
  84. }
  85. return 0;
  86. }

  

bzoj 1825: [JSOI2010]蔬菜庆典的更多相关文章

  1. bzoj1825: [JSOI2010]蔬菜庆典

    Description Input Output 对于每组数据,输出一行.若蔬菜的总价能无限制增大,输出"+inf"(不含引号).否则输出一个整数,表示所有蔬菜的最大总价.   首 ...

  2. BZOJ 2208: [Jsoi2010]连通数 tarjan bitset

    2208: [Jsoi2010]连通数 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...

  3. BZOJ 2208: [Jsoi2010]连通数( DFS )

    n只有2000,直接DFS就可以过了... -------------------------------------------------------------------------- #in ...

  4. BZOJ 1820: [JSOI2010]Express Service 快递服务( dp )

    dp(i,j,k)表示在处理第i个业务, 另外2个在j,k处. 第一维可以滚动... --------------------------------------------------------- ...

  5. BZOJ 1823: [JSOI2010]满汉全席( 2-sat )

    2-sat...假如一个评委喜好的2样中..其中一样没做, 那另一样就一定要做, 这样去建图..然后跑tarjan. 时间复杂度O((n+m)*K) ------------------------- ...

  6. bzoj 2208 [Jsoi2010]连通数

    2208: [Jsoi2010]连通数 Time Limit: 20 Sec  Memory Limit: 512 MB Description Input 输入数据第一行是图顶点的数量,一个正整数N ...

  7. 【刷题】BZOJ 4946 [Noi2017]蔬菜

    Description http://www.lydsy.com/JudgeOnline/upload/Noi2017D2.pdf Solution 网上大部分都是并查集写法,但是有大神写了非并查集写 ...

  8. BZOJ.4946.[NOI2017]蔬菜(贪心 离线)

    题目链接 因为有删除,考虑倒序处理某个p的询问. 那么每天删除xi的蔬菜就变成了每天运来xi的蔬菜.那么我们取当前最优的即可,早取晚取都一样,不需要留给后面取,还能给后面更优的留出空间. 这样就只需考 ...

  9. bzoj 1823: [JSOI2010]满汉全席 && bzoj 2199 : [Usaco2011 Jan]奶牛议会 2-sat

    noip之前学的内容了,看到题竟然忘了怎么建图了,复习一下. 2-sat 大概是对于每个元素,它有0和1两种选择,必须选一个但不能同时选.这之间又有一些二元关系,比如x&y=1等等... 先把 ...

随机推荐

  1. 【文章存档】Azure Web 应用如何修改 IIS 配置

    链接 https://docs.azure.cn/zh-cn/articles/azure-operations-guide/app-service-web/aog-app-service-web-h ...

  2. Geatpy遗传算法在曲线寻优上的初步探究

    园子里关于遗传算法的教案不少,但基于geatpy框架的并未多见,故分享此文以作参考,还望广大园友多多指教! Geatpy出自三所名校联合团队之手,是遗传算法领域的权威框架(python),其效率之高. ...

  3. MySQL基础练习(二)

    第一个例子我们编写一个 SQL 查询,列出所有超过或等于5名学生的课. 先建表 CREATE TABLE courses( student ) NOT NULL, class ) NOT NULL ) ...

  4. 基于Linux-3.9.4内核增加简单的时间片轮转功能

    简单的时间片轮转多道程序内核代码 原创作品转载请注明出处https://github.com/mengning/linuxkernel/ 作者:sa18225465 一.安装 Linux-3.9.4 ...

  5. XSS构造技巧

    利用字符编码: 百度曾经出过一个XSS漏洞,在一个<script>标签中输出一个变量,其中转义了双引号: var redirectUrl="\";alert(/XSS/ ...

  6. ltrace命令详解

    原文链接:https://ipcmen.com/ltrace 用来跟踪进程调用库函数的情况 补充说明 NAME       ltrace - A library call tracer ltrace命 ...

  7. exit命令详解

    基础命令学习目录首页 原文链接:https://www.cnblogs.com/itcomputer/p/4157859.html 用途说明 exit命令用于退出当前shell,在shell脚本中可以 ...

  8. Babel 入门教程

    Babel是一个广泛使用的转码器,可以将ES6代码转为ES5代码,从而在现有环境执行. 这意味着,你可以现在就用 ES6 编写程序,而不用担心现有环境是否支持.下面是一个例子. // 转码前 inpu ...

  9. 关于React面试题汇总

    1.redux中间件 中间件提供第三方插件的模式,自定义拦截 action -> reducer 的过程.变为 action -> middlewares -> reducer .这 ...

  10. python正则表达式,以及应用[下载图片]

    regular expresion由一系列特定字符及其组合成的字符串,用来对目标字符串进行过滤操作.. re相关知识点 python正则表达式库为re,用import re导入,在然后用re.comp ...