Shik and Travel

Time Limit: 50 Sec  Memory Limit: 512 MB

Description

  给定一棵n个点的树,保证一个点出度为2/0。

  遍历一遍,要求每条边被经过两次,第一次从根出发,最后一次到根结束,在叶子节点之间移动。

  移动一次的费用为路径上的边权之和,第一次和最后一次免费,移动的最大费用 最小可以是多少。

Input

  第一行一个n,表示点数。

  之后两个数x, y,若在第 i 行,表示 i+1 -> x 有一条权值为 y 的边。

Output

  输出一个数表示答案。

Sample Input

  7
  1 1
  1 1
  2 1
  2 1
  3 1
  3 1

Sample Output

  4

HINT

  2 < n < 131,072
  0 ≤ y ≤ 131,072

Solution

  问题的本质就是:求一个叶子节点排列,按照排列顺序走,使得两两距离<=K
  因为第一天和最后一天不花费,可以第一天从根走到一个叶子,最后一天从某一叶子走回根。
  我们首先二分答案。

  对于子树u维护二元组(a, b),表示存在方案可以 从 与u距离为a的点 出发 然后走到 与u距离为b的点,并且遍历了u中的所有叶子节点
  用个vector存一下即可。显然,若a升序则b要降序,否则是无用状态

  运用Dfs,从叶子节点往上推。我们现在考虑如何合并子树u、v的(a, b)。给一棵子树编号(a1, b1),另一棵为(a2, b2)
  我们新二元组的走法应该是 a1->b1, b1->a2, a2->b2 的,
  只要保证 b1->a2 这一条路径 权值和<=K 即可合并成(a1 + (u->fa), b2 + (v->fa))
  显然用(a1, b1)去合并只有一个有用状态:满足b1 + a2 + (u->fa) + (v->fa)<=Ka2尽量大,因为这样b2会尽量小
  枚举size较小的一边,二分一下另外一边即可。

  若推到根存在一组二元组即可行。

Code

  1. #include<iostream>
  2. #include<string>
  3. #include<algorithm>
  4. #include<cstdio>
  5. #include<cstring>
  6. #include<cstdlib>
  7. #include<cmath>
  8. #include<vector>
  9. using namespace std;
  10. typedef long long s64;
  11.  
  12. const int ONE = ;
  13. const s64 INF = 1e18;
  14.  
  15. #define next nxt
  16.  
  17. int get()
  18. {
  19. int res = , Q = ; char c;
  20. while( (c = getchar()) < || c > )
  21. if(c == '-') Q = -;
  22. if(Q) res = c - ;
  23. while( (c = getchar()) >= && c <= )
  24. res = res * + c - ;
  25. return res * Q;
  26. }
  27.  
  28. struct power
  29. {
  30. s64 a, b;
  31. bool operator <(power A) const
  32. {
  33. if(A.a != a) return a < A.a;
  34. return b < A.b;
  35. }
  36. };
  37. vector <power> A[ONE], R;
  38.  
  39. int n;
  40. int x, y;
  41. s64 l, r, K;
  42. int next[ONE], first[ONE], go[ONE], w[ONE], tot;
  43. int size[ONE], fat[ONE];
  44.  
  45. void Add(int u, int v, int z)
  46. {
  47. next[++tot] = first[u], first[u] = tot, go[tot] = v, w[tot] = z;
  48. next[++tot] = first[v], first[v] = tot, go[tot] = u, w[tot] = z;
  49. }
  50.  
  51. int dist[ONE];
  52. int len_x, len_y;
  53. s64 a1, b1, a2, b2;
  54.  
  55. int Find()
  56. {
  57. if(len_y == ) return len_y;
  58. int l = , r = len_y - ;
  59. while(l < r - )
  60. {
  61. int mid = l + r >> ;
  62. a2 = A[y][mid].a, b2 = A[y][mid].b;
  63. if(b1 + a2 + dist[x] + dist[y] <= K) l = mid;
  64. else r = mid;
  65. }
  66. a2 = A[y][r].a, b2 = A[y][r].b; if(b1 + a2 + dist[x] + dist[y] <= K) return r;
  67. a2 = A[y][l].a, b2 = A[y][l].b; if(b1 + a2 + dist[x] + dist[y] <= K) return l;
  68. return len_y;
  69. }
  70.  
  71. void Update(int u)
  72. {
  73. x = , y = ;
  74. for(int e = first[u]; e; e = next[e])
  75. if(go[e] != fat[u])
  76. if(!x) x = go[e]; else y = go[e];
  77.  
  78. if(size[x] > size[y]) swap(x, y);
  79.  
  80. len_x = A[x].size(), len_y = A[y].size();
  81.  
  82. R.clear();
  83. for(int i = ; i < len_x; i++)
  84. {
  85. a1 = A[x][i].a, b1 = A[x][i].b;
  86. if(Find() >= len_y) continue;
  87. R.push_back((power){a1 + dist[x], b2 + dist[y]});
  88. R.push_back((power){b2 + dist[y], a1 + dist[x]});
  89. }
  90.  
  91. sort(R.begin(), R.end());
  92. int len = R.size();
  93. s64 maxx = INF;
  94. for(int i = ; i < len; i++)
  95. if(R[i].b < maxx)
  96. A[u].push_back(R[i]), maxx = R[i].b;
  97. }
  98.  
  99. void Dfs(int u, int father)
  100. {
  101. size[u] = ;
  102. int pd = ;
  103. for(int e = first[u]; e; e = next[e])
  104. {
  105. int v = go[e];
  106. if(v == father) continue;
  107. fat[v] = u, dist[v] = w[e];
  108. Dfs(v, u);
  109. size[u] += size[v], pd++;
  110. if(pd == ) Update(u);
  111. }
  112. if(!pd) A[u].push_back((power){, });
  113. }
  114.  
  115. int Check()
  116. {
  117. for(int i = ; i <= n; i++)
  118. A[i].clear();
  119. Dfs(, );
  120. return A[].size() > ;
  121. }
  122.  
  123. int main()
  124. {
  125. n = get();
  126. for(int i = ; i <= n; i++)
  127. {
  128. x = get(), y = get();
  129. Add(i, x, y), r += y;
  130. }
  131.  
  132. while(l < r - )
  133. {
  134. K = l + r >> ;
  135. if(Check()) r = K;
  136. else l = K;
  137. }
  138.  
  139. K = l;
  140. if(Check()) printf("%lld", l);
  141. else printf("%lld", r);
  142. }
  • 广泛的交换

【AtCoder Grand Contest 007E】Shik and Travel [Dfs][二分答案]的更多相关文章

  1. AtCoder Grand Contest 007

    AtCoder Grand Contest 007 A - Shik and Stone 翻译 见洛谷 题解 傻逼玩意 #include<cstdio> int n,m,tot;char ...

  2. AtCoder Grand Contest 011

    AtCoder Grand Contest 011 upd:这篇咕了好久,前面几题是三周以前写的... AtCoder Grand Contest 011 A - Airport Bus 翻译 有\( ...

  3. AtCoder Grand Contest 031 简要题解

    AtCoder Grand Contest 031 Atcoder A - Colorful Subsequence description 求\(s\)中本质不同子序列的个数模\(10^9+7\). ...

  4. AtCoder Grand Contest 010

    AtCoder Grand Contest 010 A - Addition 翻译 黑板上写了\(n\)个正整数,每次会擦去两个奇偶性相同的数,然后把他们的和写会到黑板上,问最终能否只剩下一个数. 题 ...

  5. AtCoder Grand Contest 009

    AtCoder Grand Contest 009 A - Multiple Array 翻译 见洛谷 题解 从后往前考虑. #include<iostream> #include< ...

  6. AtCoder Grand Contest 006

    AtCoder Grand Contest 006 吐槽 这套题要改个名字,叫神仙结论题大赛 A - Prefix and Suffix 翻译 给定两个串,求满足前缀是\(S\),后缀是\(T\),并 ...

  7. AtCoder Grand Contest 005

    AtCoder Grand Contest 005 A - STring 翻译 给定一个只包含\(ST\)的字符串,如果出现了连续的\(ST\),就把他删去,然后所有位置前移.问最后剩下的串长. 题解 ...

  8. AtCoder Grand Contest 004

    AtCoder Grand Contest 004 A - Divide a Cuboid 翻译 给定一个\(A*B*C\)的立方体,现在要把它分成两个立方体,求出他们的最小体积差. 题解 如果有一条 ...

  9. AtCoder Grand Contest 014

    AtCoder Grand Contest 014 A - Cookie Exchanges 有三个人,分别有\(A,B,C\)块饼干,每次每个人都会把自己的饼干分成相等的两份然后给其他两个人.当其中 ...

随机推荐

  1. 父元素如果为none,子元素也是看不到的

    1.最近遇到一个问题,就是获取一个子元素的offsetwidth 的值总是为0 .原因是因为把父元素给设置成none了. 2.给元素赋值宽高 div.style.width=330+'px' 要加上p ...

  2. beta——5

    一.提供当天站立式会议照片一张: 二. 每个人的工作 (有work item 的ID) (1) 昨天已完成的工作: 对用户功能的添加. (2) 今天计划完成的工作: web发布 (3) 工作中遇到的困 ...

  3. [转帖] CentOS7 与 CentOS6的对比

    来源网站: http://blog.51cto.com/fengery/1901349 centos6.x_centos7.x差异改进明细 感谢原作者 centos官方帮助文档:https://wik ...

  4. 关闭SSD(固态硬盘)节能功能 提搞SSD性能

     此方法可以缓解比如QQ聊天时能明显感觉到打字过程不连续,0.1s左右的间歇停顿,操作系统并不会锁死,系统突然停止响应,硬盘灯狂闪,鼠标指针成为圆圈,点什么都没反应,这种状况可能会持续1-2分钟, ...

  5. Two Sum III - Data structure design

    Design and implement a TwoSum class. It should support the following operations: add and find. add - ...

  6. BZOJ3309 DZY Loves Math(莫比乌斯反演+线性筛)

    一通正常的莫比乌斯反演后,我们只需要求出g(n)=Σf(d)*μ(n/d)的前缀和就好了. 考虑怎么求g(n).当然是打表啊.设n=∏piai,n/d=∏pibi .显然若存在bi>1则这个d没 ...

  7. 01 Spring Boot 的简单配置和使用

    Spring Boot 简介 使用 Spring Boot 可以让我们快速创建一个基于 Spring 的项目,而让这个 Spring 项目跑起来我们只需要很少的配置就可以了. 创建 Spring Bo ...

  8. vyos 基础配置

    vyos 基础配置 http://www.lowefamily.com.au/2015/11/29/using-a-vyos-router-with-hyper-v/1/http://thomasvo ...

  9. oracle +plsql装完省略号不能点

    1.如图 2.复制 TNS 服务名 3.复制到 登录框的 Database ,输入用户名密码,点OK..可以进去了,省略号变成可点击状态

  10. 学习Spring Boot:(二)启动原理

    前言 主要了解前面的程序入口 @@SpringBootApplication 这个注解的结构. 正文 参考<SpringBoot揭秘 快速构建微服务体系>第三章的学习,总结下. Sprin ...