题意:

题目描述

H 国有n个城市,这n个城市用n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点。

H 国的首都爆发了一种危害性极高的传染病。当局为了控制疫情,不让疫情扩散到边境城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从首都到边境城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点。但特别要注意的是,首都是不能建立检查点的。

现在,在 H 国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队。一支军队可以在有道路连接的城市间移动,并在除首都以外的任意一个城市建立检查点,且只能在一个城市建立检查点。一支军队经过一条道路从一个城市移动到另一个城市所需要的时间等于道路的长度(单位:小时)。

请问最少需要多少个小时才能控制疫情。注意:不同的军队可以同时移动。

输入格式

第一行一个整数n,表示城市个数。

接下来的n-1行,每行3个整数u,v,w,每两个整数之间用一个空格隔开,表示从城市u到城市v有一条长为w的道路。数据保证输入的是一棵树,且根节点编号为1

接下来一行一个整数m,表示军队个数。

接下来一行m个整数,每两个整数之间用一个空格隔开,分别表示这m个军队所驻扎的城市的编号。

输出格式

共一行,包含一个整数,表示控制疫情所需要的最少时间。如果无法控制疫情则输出-1。

数据范围

洛咕,即官方数据范围:

LOJ:

吐槽:

LOJ这数据……真的天坑我艹

看LOJ数据以为$O(n^2logn)$只有30很虚,结果去看官方数据有60……

然后我$O(nlogn)$的正解不仅要开longlong还被卡常卡成95,在洛咕秒过……

SBLOJ!

题解:

由于军队可以同时移动,所以题目要求的就是使最大值最小,这种最优化问题明显二分答案;

一个结论是军队肯定离根节点越近控制的点越多,即深度越小越优,所以军队选择的策略肯定是向上走;

这样贪心的思路就是让尽量多的军队走到根节点,然后走到那些没有军队的根节点的子节点上,这样子就控制了以那个子节点为根的整个子树;

但是有些军队在时间限制内是走不到根节点的,所以要按照走不走得到根节点分类,如果走不到就留在能走到的最高的点,把这些点设为已被控制,走的到的暂时放在根节点,然后记录这些军队是从根节点的哪个子节点走上来的;

这时可以dfs一遍求出哪些点已经被控制了,注意如果一个点的所有子节点都被控制了那么这个点也算被控制了,然后记录下所有没被控制的根节点的子节点;

按照剩余的时间给所有能到达根节点的军队排序,按照到根节点的距离给没被控制的那些子节点排序,明显剩余时间多军队的去支援到根节点距离远的子节点是最优的;

但是还有个问题,就是有些军队去支援后自己来源的那个子节点反而没有军队去控制;

因此排序时要从小到大,然后优先让每个军队向下回到自己来源的那个子节点(这样做就可以忽略上到根节点又回去的过程,所以时间肯定符合),否则去支援其他子节点,最后判断能否控制所有子节点即可。

这里快速求距离用树上倍增实现。

讲的比较复杂,代码里细节也很多,写的时候要注意。

代码:

(LOJ被卡常95分,不加读入优化90分)

  1. #include<algorithm>
  2. #include<iostream>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<cmath>
  6. #include<queue>
  7. #define inf 10000000000000000
  8. #define eps 1e-9
  9. using namespace std;
  10. typedef long long ll;
  11. struct edge{
  12. int v,w,next;
  13. }a[];
  14. struct node{
  15. ll v;
  16. int id;
  17. friend bool operator <(node a,node b){
  18. return a.v<b.v;
  19. }
  20. }ar[],nd[];
  21. int n,m,u,v,w,tot=,cnt=,_cnt=,arm[],fa[][],head[];
  22. ll ans=-,l,r,sum=,dis[][];
  23. bool isin[];
  24. char buffer[],*hd,*tl;
  25. inline char Getchar(){
  26. if(hd==tl){
  27. int len=fread(buffer,,,stdin);
  28. hd=buffer,tl=hd+len;
  29. if(hd==tl)
  30. return EOF;
  31. }
  32. return *hd++;
  33. }
  34. inline int rd(){
  35. register int x=;
  36. char c;
  37. do c=Getchar();
  38. while(!isdigit(c));
  39. do{
  40. x=(x<<)+(x<<)+(c^);
  41. c=Getchar();
  42. }while(isdigit(c));
  43. return x;
  44. }
  45. void add(int u,int v,int w){
  46. a[++tot].v=v;
  47. a[tot].w=w;
  48. a[tot].next=head[u];
  49. head[u]=tot;
  50. }
  51. void dfs(int u,int ff,int ds){
  52. fa[u][]=ff;
  53. dis[u][]=ds;
  54. for(int i=;i<=;i++){
  55. fa[u][i]=fa[fa[u][i-]][i-];
  56. dis[u][i]=dis[u][i-]+dis[fa[u][i-]][i-];
  57. }
  58. for(int tmp=head[u];tmp!=-;tmp=a[tmp].next){
  59. int v=a[tmp].v;
  60. if(v!=ff){
  61. dfs(v,u,a[tmp].w);
  62. }
  63. }
  64. }
  65. void dfstf(int u,int fa){
  66. bool t1=true,t2=false;
  67. for(int tmp=head[u];tmp!=-;tmp=a[tmp].next){
  68. int v=a[tmp].v;
  69. if(v!=fa){
  70. dfstf(v,u);
  71. t1&=isin[v];
  72. t2=true;
  73. }
  74. }
  75. if(t1&&t2&&u!=)isin[u]=true;
  76. }
  77. bool chk(ll k){
  78. int nw,ret=;
  79. ll d=;
  80. for(int i=;i<=n;i++)isin[i]=false;
  81. cnt=_cnt=;
  82. for(int i=;i<=m;i++){
  83. nw=arm[i];
  84. d=;
  85. for(int j=;j>=;j--){
  86. if(fa[nw][j]&&d+dis[nw][j]<=k){
  87. d+=dis[nw][j];
  88. nw=fa[nw][j];
  89. }
  90. }
  91. if(nw!=)isin[nw]=true;
  92. else{
  93. int vv=arm[i];
  94. for(int j=;j>=;j--){
  95. if(fa[vv][j]>)vv=fa[vv][j];
  96. }
  97. ar[++cnt].v=k-d;
  98. ar[cnt].id=vv;
  99. }
  100. }
  101. dfstf(,);
  102. for(int tmp=head[];tmp!=-;tmp=a[tmp].next){
  103. int v=a[tmp].v;
  104. if(!isin[v]){
  105. nd[++_cnt].v=a[tmp].w;
  106. nd[_cnt].id=v;
  107. }
  108. }
  109. sort(ar+,ar+cnt+);
  110. sort(nd+,nd+_cnt+);
  111. nd[_cnt+].v=inf;
  112. for(int i=;i<=cnt;i++){
  113. if(!isin[ar[i].id])isin[ar[i].id]=true;
  114. else if(ar[i].v>=nd[ret].v)isin[nd[ret].id]=true;
  115. while(isin[nd[ret].id])ret++;
  116. }
  117. return ret>_cnt;
  118. }
  119. int main(){
  120. memset(head,-,sizeof(head));
  121. //scanf("%d",&n);
  122. n=rd();
  123. for(int i=;i<n;i++){
  124. //scanf("%d%d%d",&u,&v,&w);
  125. u=rd(),v=rd(),w=rd();
  126. add(u,v,w);
  127. add(v,u,w);
  128. sum+=w;
  129. }
  130. //scanf("%d",&m);
  131. m=rd();
  132. for(int i=;i<=m;i++)arm[i]=rd();//scanf("%d",&arm[i]);
  133. l=,r=sum;
  134. dfs(,,);
  135. while(l<=r){
  136. ll mid=(l+r)/;
  137. if(chk(mid))ans=mid,r=mid-;
  138. else l=mid+;
  139. }
  140. printf("%lld",ans);
  141. return ;
  142. }

[LOJ2607]【NOIP2012】疫情控制的更多相关文章

  1. Luogu 1084 NOIP2012 疫情控制 (二分,贪心,倍增)

    Luogu 1084 NOIP2012 疫情控制 (二分,贪心,倍增) Description H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树, 1 号城市是首都, 也是 ...

  2. [NOIP2012]疫情控制 贪心 二分

    题面:[NOIP2012]疫情控制 题解: 大体思路很好想,但是有个细节很难想QAQ 首先要求最大时间最小,这种一般都是二分,于是我们二分一个时间,得到一个log. 然后发现一个军队,越往上走肯定可以 ...

  3. NOIP2012 疫情控制 题解(LuoguP1084)

    NOIP2012 疫情控制 题解(LuoguP1084) 不难发现,如果一个点向上移动一定能控制更多的点,所以可以二分时间,判断是否可行. 但根节点不能不能控制,存在以当前时间可以走到根节点的点,可使 ...

  4. noip2012 疫情控制

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

  5. NOIP2012疫情控制(二分答案+倍增+贪心)

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

  6. [NOIP2012]疫情控制(二分答案+倍增+贪心)

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

  7. [NOIp2012]疫情控制 题解

    好久没更,强迫自己写一篇. 神 tm 大预言家出的题 注意到如果 \(x\) 小时可以控制住疫情,则 \(\forall x'>x\) 必然也可以控制住疫情,显然答案具有单调性,可以二分答案. ...

  8. NOIP2012疫情控制(二分答案+树上贪心)

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

  9. noip2012疫情控制 题解

    题目大意 给出一棵n个节点的树,根是1,要在除根节点以外的点建立检查点,使得从每条根到叶子的路径上都至少存在一个检查点.检查点由军队来建立.初始军队的位置是给定的,移动军队走一条边需要花费这条边的权值 ...

  10. luogu1084 [NOIp2012]疫情控制 (二分答案+倍增+dfs序)

    先二分出一个时间,把每个军队倍增往上跳到不能再跳 然后如果它能到1号点,就记下来它跳到1号点后剩余的时间:如果不能,就让它就地扎根,记一记它覆盖了哪些叶节点(我在这里用了dfs序+差分,其实直接dfs ...

随机推荐

  1. Grand Central Dispatch-thread pool pattern

    Grand Central Dispatch (GCD) is a technology developed by Apple Inc. to optimize application support ...

  2. JQuery选择器排除某元素实现js代码

    使用JQuery选择器实现排除某一大元素下的某一元素的核心代码是使用.not()方法,如下所示: $("button").not("#save").attr(& ...

  3. python链接mysql数据库

    1.安装pycharm python3.6    pip 在windows+R  cmd where pip pip install mysql-client 如何看自已mysql-client有没有 ...

  4. elment表格分页

    项目的时候遇到了一个分页的bug,经过分析Element源码之后找到了问题所在,现在把这个问题及解决方法记录下来. 项目中要实现的功能是用户选择查看表格的时候在任意页面点击查询,得到结果之后要展示的页 ...

  5. rest-framework框架

    rest-framework框架是Django里面非常重要的框架,但提到rest-framework框架就不得不说两种请求方式,那就是CBV和FBV. FBV(function base views) ...

  6. 使用InstelliJ IDEA创建Spring MVC应用程序

    环境版本 Windows 8.1 IDE:InstelliJ IDEA 13    Spring:Spring 4.1.1 & Spring MVC 4.1.1    WebLogic 10. ...

  7. jvm 虚拟机参数_堆内存分配

    1.参数 -XX:+PrintGC 只要遇到 GC 就会打印日志 -XX:+UseSerialGC 配置串行回收器 -XX:+PrintGCDetails 查看详细信息,包括各个区的情况 -XX:+P ...

  8. TCP的可靠传输(依赖流量控制、拥塞控制、连续ARQ)

    TCP可靠性表现在它向应用层提供的数据是无差错,有序,无丢失,即递交的和发送的数据是一样的. 可靠性依赖于流量控制.拥塞控制.连续ARQ等技术 <TCP/IP详解>中的“分组”是不是就是报 ...

  9. ruby on rails错误undefined method `title&#39; for nil:NilClass

    首先搞清楚这句话,在 Ruby 中,方法分为 public.private 和 protected 三种,仅仅有 public 方法才干作为控制器的动作. 我的出错的代码例如以下: controlle ...

  10. 游标和动态SQL

    游标类别:静态游标(指在编译的时候,游标就与一个select语句进行了静态绑定的游标.这样的游标仅仅能作用于一个查询语句)和动态游标(就是希望我们的查询语句在执行的时候才跟游标绑定.为了使用动态游标, ...