题目

细节比较多的二分+跟LCA倍增差不多的思想

首先有这样一个贪心思路,深度越低的检查点越好,而最长时间和深度具有单调性,即给定时间越长,每个军队能向更浅的地方放置检查点。因此可以考虑二分时间,然后判断军队是否可以放置在控制疫情的地方。

但是有的军队需要先满足自己当前所在的节点,然后此节点如果有多个军队,其他军队跳到1节点,再跳到1节点的其他子树,这里又有一个贪心策略,就是每个军队跳到1的剩余时间:二分的当前时间减去到1节点的距离越大,就要跳到1的另一个子树里据1最远的点,这样才能更好地使得控制疫情。

  1. #include <bits/stdc++.h>
  2. #define N 1001001
  3. using namespace std;
  4. struct edg {
  5. int to, nex, len;
  6. }e[N];
  7. struct tem {
  8. int id, len;
  9. }a[N], b[N];
  10. int n, m, cnt, lin[N], vis[N], vis2[N], army[N], dep[N], fa[N][19], dis[N][19];//fa[i][j]表示军队向上跳j次所到达的位置,dis表示此时所用的时间。
  11. //vis表示该点包括的叶子节点是否被完全覆盖
  12. bool cmp(tem x, tem y)
  13. {
  14. return x.len < y.len;
  15. }
  16. inline void add(int f, int t, int l)
  17. {
  18. e[++cnt].len = l;
  19. e[cnt].to = t;
  20. e[cnt].nex = lin[f];
  21. lin[f] = cnt;
  22. }
  23. void dfs(int now, int f)
  24. {
  25. fa[now][0] = f;
  26. dep[now] = dep[f] + 1;
  27. for (int i = lin[now]; i; i = e[i].nex)
  28. {
  29. int to = e[i].to;
  30. if (to == f) continue;
  31. dis[to][0] = e[i].len;
  32. dfs(to, now);
  33. }
  34. }
  35. void bF(int now)//判断该点的所有叶子节点是否全都被覆盖
  36. {
  37. int b1 = 1, b2 = 0;
  38. if (vis[now]) return;
  39. for (int i = lin[now]; i; i = e[i].nex)
  40. {
  41. int to = e[i].to;
  42. if (to == fa[now][0])
  43. continue;
  44. b2 = 1;
  45. bF(to);
  46. if (!vis[to])
  47. b1 = 0;
  48. }
  49. if (b1 && b2 && now != 1)
  50. vis[now] = 1;
  51. }
  52. bool check(int mid)//使每个军队都尽可能的往上跳,直到距离比mid大才停止。
  53. {
  54. memset(vis, 0, sizeof(vis));
  55. memset(vis2, 0, sizeof(vis2));
  56. int tnt1 = 0, tnt2 = 0;
  57. for (int i = 1; i <= m; i++)
  58. {
  59. int u = army[i], dn = 0;
  60. for (int j = 18; j >= 0; j--) if (dn + dis[u][j] <= mid && fa[u][j] != 0) dn += dis[u][j], u = fa[u][j];
  61. if (u != 1)//如果此点不为1说明此点可以被覆盖。
  62. vis[u] = 1;
  63. else
  64. {
  65. a[++tnt1].len = mid - dn;
  66. int u2 = army[i];
  67. for (int j = 18; j >= 0; j--) if (fa[u2][j] > 1) u2 = fa[u2][j];
  68. a[tnt1].id = u2;
  69. }
  70. }
  71. bF(1);
  72. for (int i = lin[1]; i; i = e[i].nex)//枚举深度为2的点
  73. {
  74. int to = e[i].to;
  75. if (vis[to]) continue;//找到没有完全覆盖完的to; 然后加以覆盖。 选一定要选深度最浅的,所以选择深度为2的,这样选择一定是最优解。
  76. b[++tnt2].id = to, b[tnt2].len = e[i].len;
  77. }
  78. sort(a + 1, a + 1 + tnt1, cmp);//a的len是剩余的时间
  79. sort(b + 1, b + 1 + tnt2, cmp);//b的len是需要的时间, 他们的时间相加
  80. int j = 1;
  81. for (int i = 1; i <= tnt1; i++)
  82. {
  83. if (!vis[a[i].id]) vis[a[i].id] = 1;//先把此点给覆盖了。
  84. else if (a[i].len >= b[j].len) vis[b[j].id] = 1;
  85. while (vis[b[j].id] && j <= tnt2) j++;
  86. }
  87. if (j > tnt2)
  88. return 1;
  89. else
  90. return 0;
  91. }
  92. inline void init()
  93. {
  94. scanf("%d", &n);
  95. for (int i = 1, u, v, w; i < n; i++)
  96. {
  97. scanf("%d%d%d", &u, &v, &w);
  98. add(u, v, w);
  99. add(v, u, w);
  100. }
  101. scanf("%d", &m);
  102. for (int i = 1; i <= m; i++)
  103. scanf("%d", &army[i]);
  104. dfs(1, 0);
  105. for (int j = 1; j <= 18; j++)
  106. for (int i = 1; i <= n; i++)
  107. {
  108. fa[i][j] = fa[fa[i][j - 1]][j - 1];
  109. dis[i][j] = dis[i][j - 1] + dis[fa[i][j - 1]][j - 1];//dis[i][j]是i向上跳j步所走的路径长度,此叶子节点的意思是最深的节点
  110. }
  111. }
  112. int main()
  113. {
  114. init();
  115. int ans, l = 0, r = 70000000;
  116. while (l <= r)
  117. {
  118. int mid = (l + r) >> 1;
  119. if (check(mid))
  120. ans = mid, r = mid - 1;
  121. else
  122. l = mid + 1;
  123. }
  124. printf("%d", ans);
  125. return 0;
  126. }

洛谷P1084 疫情控制的更多相关文章

  1. 洛谷P1084 疫情控制(NOIP2012)(二分答案,贪心,树形DP)

    洛谷题目传送门 费了几个小时杠掉此题,如果不是那水水的数据的话,跟列队的难度真的是有得一比... 话说蒟蒻仔细翻了所有的题解,发现巨佬写的都是倍增,复杂度是\(O(n\log n\log nw)\)的 ...

  2. [NOIP2012] 提高组 洛谷P1084 疫情控制

    题目描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都, 也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散 ...

  3. NOIP2012 洛谷P1084 疫情控制

    Description: H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控制疫情 ...

  4. 洛谷 P1084 疫情控制 —— 二分+码力

    题目:https://www.luogu.org/problemnew/show/P1084 5个月前曾经写过一次,某个上学日的深夜,精疲力竭后只有区区10分,从此没管... #include< ...

  5. 洛谷P1084 疫情控制 [noip2012] 贪心+树论+二分答案 (还有个小bugQAQ

    正解:贪心+倍增+二分答案 解题报告: 正好想做noip的题目然后又想落实学长之前讲的题?于是就找上了这题 其实之前做过,70,然后实在细节太多太复杂就不了了之,现在再看一遍感觉又一脸懵了... 从标 ...

  6. 2018.09.26洛谷P1084 疫情控制(二分+倍增)

    传送门 好题啊. 题目要求的最大值最小,看到这里自然想到要二分答案. 关键在于怎么检验. 显然对于每个点向根走比向叶节点更优. 因此我们二分答案之后,用倍增将每个点都向上跳到跳不动为止. 这时我们ch ...

  7. 洛谷P1084 疫情控制(贪心+倍增)

    这个题以前写过一遍,现在再来写,感觉以前感觉特别不好写的细节现在好些多了,还是有进步吧. 这个题的核心思想就是贪心+二分.因为要求最小时间,直接来求问题将会变得十分麻烦,但是如果转换为二分答案来判断可 ...

  8. 洛谷P1084 [NOIP2012提高组Day2T3]疫情控制

    P1084 疫情控制 题目描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控 ...

  9. NOIP2012 D2 T3 疫情控制 洛谷P1084

    题目链接:https://www.luogu.org/problemnew/show/P1084 算法:倍增,二分答案,贪心 + 瞎搞.. 背景:上学长的数论课啥也听不懂,于是前去提高组找安慰.不巧碰 ...

随机推荐

  1. Web应用调用.Net Core API

    Web应用调用.Net Core API 一.新建Web Application应用: 选择Web Application 新建好之后页面如下: 二.新建Model.新建Model文件夹并建立apiM ...

  2. org.springframework.stereotype

    org.springframework.stereotype 1.@controller 控制器(注入服务) 2.@service 服务(注入dao) 3.@repository dao(实现dao访 ...

  3. 千万不要用window自带文本编辑器编辑配置文件或者代码

    1 引言 用windows自带的text文本在最前面会带入看不到的BOM,导致异常 2 代码 package main import ( "strings" "fmt&q ...

  4. SpringMVC中的400错误,The request sent by the client was syntactically incorrect.

    在其他对象属性类型一样情况下,只需要创建一个类,再在springmvc.xml中添加配置: package com.ujiuye.common; import org.springframework. ...

  5. 前端自动显示信息的小demo

    效果: //来到这个页面立即请求,展示客户公司名称 $(function () { $.ajax({ type:"GET", url:"${pageContext.req ...

  6. Android-----ListView组件使用(实现点击选择)

    在Android中的ListView选单组件,是以下列表方式来列出选项,供用户选择. ListView组件属性设置: 创建spinner组件时,只需要设置一项entries属性即可使用.此属性是设置要 ...

  7. redis-存储命令

    一.String类型: 1.赋值/取值 set key valueget key 2.设置/获取多个键值   mset key1 value1 key2 value2 …   mget key1 ke ...

  8. springboot 集成百度的唯一ID生成器

    UidGenerator是百度开源的Java语言实现,基于Snowflake算法的唯一ID生成器.而且,它非常适合虚拟环境,比如:Docker.另外,它通过消费未来时间克服了雪花算法的并发限制.Uid ...

  9. VS创建C工程

    打开VS编辑器: 填写项目名称,控制项目位置,创建: 在源文件中添加新项: 填写文件名称,修改后缀: 编写一个简单的hello word编译看看windows环境支持如何:

  10. elastic-job-lite-console后台以服务形式运行

    原文:https://blog.csdn.net/u012637358/article/details/84846923 方式1:命令让程序一直在后台运行 nohup ./bin/start.sh & ...