题目描述

公元 2044 年,人类进入了宇宙纪元。L 国有 n 个星球,还有 n−1 条双向航道,每条航道建立在两个星球之间,这 n−1 条航道连通了 L 国的所有星球。小 P 掌管一家物流公司, 该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从 ui 号星球沿最快的宇航路径飞行到 vi 号星球去。显然,飞船驶过一条航道是需要时间的,对于航道 j,任意飞船驶过它所花费的时间为 tj,并且任意两艘飞船之间不会产生任何干扰。为了鼓励科技创新, L 国国王同意小 P 的物流公司参与 L 国的航道建设,即允许小P 把某一条航道改造成虫洞,飞船驶过虫洞不消耗时间。在虫洞的建设完成前小 P 的物流公司就预接了 m 个运输计划。在虫洞建设完成后,这 m 个运输计划会同时开始,所有飞船一起出发。当这 m 个运输计划都完成时,小 P 的物流公司的阶段性工作就完成了。如果小 P 可以自由选择将哪一条航道改造成虫洞, 试求出小 P 的物流公司完成阶段性工作所需要的最短时间是多少?

输入

第一行包括两个正整数 n,m,表示 L 国中星球的数量及小 P 公司预接的运输计划的数量,星球从 1 到 n 编号。接下来 n−1 行描述航道的建设情况,其中第 i 行包含三个整数 ai,bi 和 ti,表示第 i 条双向航道修建在 ai 与 bi 两个星球之间,任意飞船驶过它所花费的时间为 ti。数据保证 1≤ai,bi≤n 且 0≤ti≤1000。接下来 m 行描述运输计划的情况,其中第 j 行包含两个正整数 uj 和 vj,表示第 j 个运输计划是从 uj 号星球飞往 vj号星球。数据保证 1≤ui,vi≤n

输出

输出文件只包含一个整数,表示小 P 的物流公司完成阶段性工作所需要的最短时间。

样例输入

6 3
1 2 3
1 6 4
3 1 7
4 3 6
3 5 5
3 6
2 5
4 5

样例输出

11

提示

将第 1 条航道改造成虫洞: 则三个计划耗时分别为:11,12,11,故需要花费的时间为 12。

将第 2 条航道改造成虫洞: 则三个计划耗时分别为:7,15,11,故需要花费的时间为 15。

将第 3 条航道改造成虫洞: 则三个计划耗时分别为:4,8,11,故需要花费的时间为 11。

将第 4 条航道改造成虫洞: 则三个计划耗时分别为:11,15,5,故需要花费的时间为 15。

将第 5 条航道改造成虫洞: 则三个计划耗时分别为:11,10,6,故需要花费的时间为 11。

故将第 3 条或第 5 条航道改造成虫洞均可使得完成阶段性工作的耗时最短,需要花费的时间为 11。


题解

二分答案+LCA(这里使用树剖求LCA)+差分

先预处理一下每个计划的时间和最近公共祖先(非常重要,影响时间复杂度),

然后二分答案,记录所有时间大于mid的计划的边的交集,这里使用差分数组。

然后用最长的计划时间减去交集中的最大边,并与mid比较即可。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. #define N 300001
  5. using namespace std;
  6. int fa[N] , deep[N] , bl[N] , si[N] , dis[N] , vf[N] , tot , queue[N];
  7. int head[N] , to[N << 1] , val[N << 1] , next[N << 1] , cnt;
  8. int sum[N] , n , be[N] , en[N] , planval[N] , m , f[N];
  9. inline int read()
  10. {
  11. int num = 0;
  12. char ch = getchar();
  13. while(ch < '0' || ch > '9') ch = getchar();
  14. while(ch >= '0' && ch <= '9') num = num * 10 + ch - '0' , ch = getchar();
  15. return num;
  16. }
  17. void add(int x , int y , int z)
  18. {
  19. to[++cnt] = y;
  20. val[cnt] = z;
  21. next[cnt] = head[x];
  22. head[x] = cnt;
  23. }
  24. void dfs1(int x)
  25. {
  26. int i;
  27. si[x] = 1;
  28. for(i = head[x] ; i ; i = next[i])
  29. {
  30. if(to[i] != fa[x])
  31. {
  32. fa[to[i]] = x;
  33. deep[to[i]] = deep[x] + 1;
  34. vf[to[i]] = val[i];
  35. dfs1(to[i]);
  36. si[x] += si[to[i]];
  37. }
  38. }
  39. }
  40. void dfs2(int x , int c)
  41. {
  42. int i , k = 0 , d;
  43. bl[x] = c;
  44. queue[++tot] = x;
  45. for(i = head[x] ; i ; i = next[i])
  46. {
  47. if(to[i] != fa[x] && si[to[i]] > si[k])
  48. {
  49. k = to[i];
  50. d = val[i];
  51. }
  52. }
  53. if(k)
  54. {
  55. dis[k] = dis[x] + d;
  56. dfs2(k , c);
  57. for(i = head[x] ; i ; i = next[i])
  58. if(to[i] != fa[x] && to[i] != k)
  59. dfs2(to[i] , to[i]);
  60. }
  61. }
  62. int getplan(int x , int y)
  63. {
  64. int ans = 0;
  65. while(bl[x] != bl[y])
  66. {
  67. if(deep[bl[x]] < deep[bl[y]])
  68. swap(x , y);
  69. ans += dis[x] + vf[bl[x]];
  70. x = fa[bl[x]];
  71. }
  72. if(deep[x] < deep[y])
  73. swap(x , y);
  74. ans += dis[x] - dis[y];
  75. return ans;
  76. }
  77. int getlca(int x , int y)
  78. {
  79. while(bl[x] != bl[y])
  80. {
  81. if(deep[bl[x]] < deep[bl[y]])
  82. swap(x , y);
  83. x = fa[bl[x]];
  84. }
  85. if(deep[x] < deep[y])
  86. return x;
  87. return y;
  88. }
  89. bool check(int mid)
  90. {
  91. memset(sum , 0 , sizeof(sum));
  92. int i , maxn = 0 , csum = 0 , maxroad = 0;
  93. for(i = 1 ; i <= m ; i ++ )
  94. {
  95. if(planval[i] > mid)
  96. {
  97. sum[be[i]] ++ ;
  98. sum[en[i]] ++ ;
  99. sum[f[i]] -= 2;
  100. if(maxn < planval[i])
  101. maxn = planval[i];
  102. csum ++ ;
  103. }
  104. }
  105. for(i = n ; i >= 2 ; i -- )
  106. {
  107. sum[fa[queue[i]]] += sum[queue[i]];
  108. if(sum[queue[i]] == csum)
  109. maxroad = max(maxroad , vf[queue[i]]);
  110. }
  111. return maxn - maxroad <= mid;
  112. }
  113. int main()
  114. {
  115. int i , x , y , z , ans , l = 0 , r = -1;
  116. n = read();
  117. m = read();
  118. for(i = 1 ; i < n ; i ++ )
  119. {
  120. x = read();
  121. y = read();
  122. z = read();
  123. add(x , y , z);
  124. add(y , x , z);
  125. }
  126. dfs1(1);
  127. dfs2(1 , 1);
  128. for(i = 1 ; i <= m ; i ++ )
  129. {
  130. be[i] = read();
  131. en[i] = read();
  132. planval[i] = getplan(be[i] , en[i]);
  133. f[i] = getlca(be[i] , en[i]);
  134. if(r < planval[i])
  135. r = planval[i];
  136. }
  137. while(l <= r)
  138. {
  139. int mid = (l + r) >> 1;
  140. if(check(mid))
  141. {
  142. ans = mid;
  143. r = mid - 1;
  144. }
  145. else
  146. l = mid + 1;
  147. }
  148. printf("%d\n" , ans);
  149. return 0;
  150. }

【bzoj4326】[NOIP2015]运输计划的更多相关文章

  1. [bzoj4326][NOIP2015]运输计划

    Description 公元2044年,人类进入了宇宙纪元. 国有个星球,还有条双向航道,每条航道建立在两个星球之间,这条航道连通了国的所有星球. 小掌管一家物流公司,该公司有很多个运输计划,每个运输 ...

  2. bzoj4326: NOIP2015 运输计划(二分+LCA+树上差分)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4326 题目大意:有一颗含有n个顶点的树,每两个点之间有一个边权,现在有m个运输计划,每个 ...

  3. 2018.09.26 bzoj4326: NOIP2015 运输计划(二分+树上差分)

    传送门 简单树上操作. 先转边权为点权. 显然所有的询问操作对应的路径会有一些交点,那么我们可以直接二分答案,对于所有大于二分值的询问用树上差分维护,最后dfs一遍每个点被覆盖了几次,当前情况合法当且 ...

  4. [BZOJ4326][codevs4632][codevs5440][UOJ#150][NOIP2015]运输计划

    [BZOJ4326][codevs4632][codevs5440][UOJ#150][NOIP2015]运输计划 试题描述 公元 2044 年,人类进入了宇宙纪元. L 国有 n 个星球,还有 n− ...

  5. NOIP2015 运输计划(bzoj4326)

    4326: NOIP2015 运输计划 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 886  Solved: 574[Submit][Status] ...

  6. bzoj 4326: NOIP2015 运输计划

    4326: NOIP2015 运输计划 Time Limit: 30 Sec Memory Limit: 128 MB Description 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个 ...

  7. 【BZOJ-4326】运输计划 树链剖分 + 树上差分 + 二分

    4326: NOIP2015 运输计划 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 703  Solved: 461[Submit][Status] ...

  8. [NOIP2015]运输计划 D2 T3 LCA+二分答案+差分数组

    [NOIP2015]运输计划 D2 T3 Description 公元2044年,人类进入了宇宙纪元. L国有n个星球,还有n-1条双向航道,每条航道建立在两个星球之间,这n-1条航道连通了L国的所有 ...

  9. NOIP2015 运输计划(二分+LCA+差分)

    4326: NOIP2015 运输计划 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 308  Solved: 208[Submit][Status] ...

  10. 数据结构(树链剖分):COGS 2109. [NOIP2015] 运输计划

    2109. [NOIP2015] 运输计划 ★★★   输入文件:transport.in   输出文件:transport.out   简单对比时间限制:1 s   内存限制:256 MB [题目描 ...

随机推荐

  1. 报表开发工具Finereport移动端app js接口列表【全】

    应用报表工具Finereport的开发人员会发现其移动端app 同样也推出了很多js接口,那这些接口到底有多少,其移动端又有哪些地方支持调用js,这些接口具体又该如何调用呢.根据我平时的开发经验,给大 ...

  2. ASP.NET Core--根据方案来限制身份

    翻译如下: 在某些情况下,比如单页的应用程序,可以与多种认证来方式结合.例如,您的应用程序可能使用基于Cookie的身份验证来登录和JavaScript的请求承载认证.在某些情况下,可能一个授权验证的 ...

  3. java异常面试题

    1.try{}里有一个return语句,那么紧跟在这个try后的finally {}里的code会不会被执行,什么时候被执行,在return前还是后? 也许你的答案是在return之前,但往更细地说, ...

  4. Freemarker与普通java

    package com.sxt.test.freemarker; import java.io.File; import java.io.OutputStreamWriter; import java ...

  5. [备份]破解Xamarin

    [转]试用了一阵子Mono For Android,今天到期了,,囊中羞涩,只好破解. 说是要在vs2013的英文界面下运行破解包,不知道是真是假,下载并安装了一个. 然后又下载了破解包.是个名为xa ...

  6. codeforces 711E. ZS and The Birthday Paradox 概率

    已知一年365天找23个人有2个人在同一天生日的概率 > 50% 给出n,k ,表示现在一年有2^n天,找k个人,有2个人在同一天生日的概率,求出来的概率是a/b形式,化到最简形式,由于a,b可 ...

  7. 2016网络大事记 mark

    记录2016年每天的大事件. 2016年01月07日     快播庭审.辩护人各种出彩. 2016年01月09日     乐视多个贴吧被爆.百度出面平息. 2016年01月10日     斗鱼TV造人 ...

  8. 【跟着子迟品 underscore】JavaScript 数组展开以及重要的内部方法 flatten

    Why underscore (觉得这一段眼熟的童鞋可以直接跳到正文了...) 最近开始看 underscore.js 源码,并将 underscore.js 源码解读 放在了我的 2016 计划中. ...

  9. 【跟着子迟品 underscore】常用类型判断以及一些有用的工具方法

    Why underscore 最近开始看 underscore.js 源码,并将 underscore.js 源码解读 放在了我的 2016 计划中. 阅读一些著名框架类库的源码,就好像和一个个大师对 ...

  10. CSS基本知识4-CSS行模型

    display:inline.block.inline-block block元素的特点是: 总是在新行上开始: 高度,行高以及顶和底边距都可控制: 宽度缺省是它的容器的100%,除非设定一个宽度 i ...