【题意】n个点的树,1为根,要求删除一些点使得截断根节点和所有叶子结点的路径(不能删根,可以删叶子)。有m支军队在m个点上,每时刻所有军队可以走一步,最终走到的地方就是删除的点,求最短时间。

【算法】二分,贪心,倍增

【题解】

所有点同时走路,求最短时间,这样的询问通常考虑二分转化为判定性问题。(实际上,这题用二分确实没有想到,如果能想到二分整道题就好写一些了)

容易发现,每支军队贪心地往上走最优。

那么对于二分的时间,有一部分军队可以到达根,A数组记录这些军队到达根后的剩余时间,待会可以走到第二层覆盖其它节点。

有一部分军队不能到达根,处理出这些军队能覆盖多少二层节点,B数组不能覆盖的二层节点到根的路径。

AB各自排序之后,对应匹配,若A能将B全部匹配就可以满足要求,否则不能。

还有一个问题,一个军队虽然不能到达根后返回来覆盖自己,但可以直接不去根。解决方法是从小到大枚举A时,如果该点本身的二层节点还没覆盖就直接覆盖(因为该点本来就是最劣的,只要能覆盖一个二层结点就不亏)。

最后的问题是处理出不能到达根的军队能覆盖多少二层结点?可以对每个军队倍增,也可以直接一遍dfs。

dfs的具体做法是:c[x]表示x被覆盖,t[x]表示x子树的军队到x的最大剩余时间。c[x] = c[son[x]]=1 || t[x]>=0。son[x]表示x的所有儿子。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<cctype>
  4. #include<algorithm>
  5. #define ll long long
  6. using namespace std;
  7. int read(){
  8. char c;int s=,t=;
  9. while(!isdigit(c=getchar()))if(c=='-')t=-;
  10. do{s=s*+c-'';}while(isdigit(c=getchar()));
  11. return s*t;
  12. }
  13. const int maxn=;
  14. int n,m,tot,first[maxn],top[maxn],a[maxn];
  15. ll dis[maxn],t[maxn];
  16. bool b[maxn],c[maxn];
  17. struct edge{int v,w,from;}e[maxn*];
  18. void insert(int u,int v,int w){tot++;e[tot].v=v;e[tot].w=w;e[tot].from=first[u];first[u]=tot;}
  19. void DFS(int x,int fa,int tp){
  20. top[x]=tp;
  21. for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa){
  22. dis[e[i].v]=dis[x]+e[i].w;//yu ju shun xu
  23. DFS(e[i].v,x,tp);
  24. }
  25. }
  26. void dfs(int x,int fa){
  27. c[x]=;
  28. for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa){c[x]=;break;}
  29. for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa){
  30. dfs(e[i].v,x);
  31. c[x]&=c[e[i].v];
  32. t[x]=max(t[x],t[e[i].v]-e[i].w);
  33. }
  34. if(t[x]>=)c[x]=;
  35. }
  36. int totA,totB;
  37. struct cyc{ll num;int id;}A[maxn],B[maxn];//
  38. bool cmp(cyc a,cyc b){return a.num<b.num;}
  39. bool check(ll time){
  40. memset(t,-,sizeof(t));
  41. totA=;totB=;
  42. for(int i=;i<=m;i++)if(dis[a[i]]<=time)b[i]=,A[++totA].num=time-dis[a[i]],A[totA].id=top[a[i]];
  43. else b[i]=,t[a[i]]=time;
  44. dfs(,);
  45. for(int i=first[];i;i=e[i].from)if(!c[e[i].v])B[++totB].num=e[i].w,B[totB].id=e[i].v;
  46. sort(A+,A+totA+,cmp);sort(B+,B+totB+,cmp);
  47. int now=;
  48. for(int i=;i<=totA;i++){
  49. while(now<=totB&&c[B[now].id])now++;
  50. if(!c[A[i].id]){c[A[i].id]=;continue;}
  51. if(now<=totB&&A[i].num>=B[now].num){c[B[now++].id]=;}
  52. }
  53. while(now<=totB&&c[B[now].id])now++;//
  54. if(now>=totB+)return ;
  55. return ;
  56. }
  57. int main(){
  58. n=read();
  59. for(int i=;i<n;i++){
  60. int u=read(),v=read(),w=read();
  61. insert(u,v,w);insert(v,u,w);
  62. }
  63. memset(dis,,sizeof(dis));
  64. for(int i=first[];i;i=e[i].from)dis[e[i].v]=e[i].w,DFS(e[i].v,,e[i].v);
  65. m=read();
  66. for(int i=;i<=m;i++)a[i]=read();
  67. ll l=,r=1ll*n*1e9+,mid;
  68. while(l<r){
  69. mid=(l+r)>>;
  70. if(check(mid))r=mid;else l=mid+;
  71. }
  72. if(r>1ll*n*1e9)printf("-1");else printf("%lld",l);
  73. return ;
  74. }

【NOIP】提高组2012 疫情控制的更多相关文章

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

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

  2. 【noip 2012】提高组Day2T3.疫情控制

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

  3. luogu P1038借教室【Noip提高组2012】

    这道题我读完题目的第一感觉是: 这不就是个线段树??用线段树维护区间最小值,检查是否满足订单要求即可判断. 对于修改操作直接在区间上进行. 据说会卡一卡线段树,但是貌似写一个懒标记,连zkw线段树都不 ...

  4. NOIP提高组2004 合并果子题解

    NOIP提高组2004 合并果子题解 描述:在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. 每一次合并,多多可以把两堆果子合并到一起,消 ...

  5. 计蒜客 NOIP 提高组模拟竞赛第一试 补记

    计蒜客 NOIP 提高组模拟竞赛第一试 补记 A. 广场车神 题目大意: 一个\(n\times m(n,m\le2000)\)的网格,初始时位于左下角的\((1,1)\)处,终点在右上角的\((n, ...

  6. 1043 方格取数 2000 noip 提高组

    1043 方格取数  2000 noip 提高组 题目描述 Description 设有N*N的方格图(N<=10,我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0.如下图所示(见样 ...

  7. [NOIP提高组2018]货币系统

    [TOC] 题目名称:货币系统 来源:2018年NOIP提高组 链接 博客链接 CSDN 洛谷博客 洛谷题解 题目链接 LibreOJ(2951) 洛谷(P5020) 大视野在线评测(1425) 题目 ...

  8. NOIP提高组初赛难题总结

    NOIP提高组初赛难题总结 注:笔者开始写本文章时noip初赛新题型还未公布,故会含有一些比较老的内容,敬请谅解. 约定: 若无特殊说明,本文中未知数均为整数 [表达式] 表示:在表达式成立时它的值为 ...

  9. 津津的储蓄计划 NOIp提高组2004

    这个题目当年困扰了我许久,现在来反思一下 本文为博客园ShyButHandsome的原创作品,转载请注明出处 右边有目录,方便快速浏览 题目描述 津津的零花钱一直都是自己管理.每个月的月初妈妈给津津\ ...

随机推荐

  1. IOS开发NSBundle使用

    bundle是一个目录,其中包含了程序会使用到的资源. 这些资源包含了如图像,声音,编译好的代码,nib文件(用户也会把bundle称为plug-in). 对应bundle,cocoa提供了类NSBu ...

  2. <Effective C++>读书摘要--Inheritance and Object-Oriented Design<二>

    <Item 36> Never redefine an inherited non-virtual function 1.如下代码通过不同指针调用同一个对象的同一个函数会产生不同的行为Th ...

  3. Swagger Authorization:bearer <token>

    1.添加如下代码 /** * * @SWG\SecurityScheme( * securityDefinition="Bearer", * type="apiKey&q ...

  4. ZOJ 2110 C - Tempter of the Bone

    https://vjudge.net/contest/67836#problem/C The doggie found a bone in an ancient maze, which fascina ...

  5. js设计模式之代理模式以及订阅发布模式

    为啥将两种模式放在一起呢?因为这样文章比较长啊. 写博客的目的我觉得首要目的是整理自己的知识点,进而优化个人所得知识体系.知识成为个人的知识,就在于能够用自己的话表达同一种意义. 本文是设计模式系列文 ...

  6. Ubuntu安装配置JDK、Tomcat、SVN服务器

    一.配置jdk 1.下载JDK http://www.oracle.com/technetwork/java/javase/downloads/index-jsp-138363.html 注:笔者是直 ...

  7. GSL介绍【转】

    GSL(GNU Scientific Library)是一个C写成的用于科学计算的库,下面是一些相关的包 http://www.thebigdata.cn/JiShuBoKe/5612.html

  8. 【hdu4507】吉哥系列故事——恨7不成妻 数位dp

    题目描述 求 $[L,R]$ 内满足:数位中不包含7.数位之和不是7的倍数.本身不是7的倍数 的所有数的平方和 mod $10^9+7$ . 输入 输入数据的第一行是case数T(1 <= T ...

  9. Codeforces Round #469 (Div. 2) F. Curfew

    贪心 题目大意,有2个宿管分别从1和n开始检查房间,记录人数不为n的房间个数,然后锁住房间. 没有被锁的房间中的学生可以选择藏在床底,留在原地,或者转移(最远转移d个房间)   然后抄了网上大神的代码 ...

  10. [SCOI2007]组队 差分

    题面:[SCOI2007]组队 题解: 一开始固定H然后找性质找了很久也没有找到任何有用的东西...... 然后大佬告诉我一个神奇的方法... 首先我们化一波式子: 设$H$表示高度的最小值,$V$表 ...