题目:https://www.luogu.org/problemnew/show/P1084

5个月前曾经写过一次,某个上学日的深夜,精疲力竭后只有区区10分,从此没管...

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. #include<queue>
  6. #define ll long long
  7. using namespace std;
  8. priority_queue< pair<int,int> >q1,q2;
  9. int const MAXN=;
  10. int n,m,head[MAXN],ct,ans,fa[MAXN],sid[MAXN],lf,lef[MAXN],gr[MAXN];
  11. ll l,r;
  12. bool vis[MAXN],in[MAXN];
  13. struct N{
  14. int to,next,w;
  15. N(int t=,int n=,int w=):to(t),next(n),w(w) {}
  16. }edge[MAXN<<];
  17. struct E{
  18. int st,pos;
  19. ll rest;
  20. }am[MAXN];
  21. void add(int x,int y,int z)
  22. {
  23. edge[++ct]=N(y,head[x],z);head[x]=ct;
  24. edge[++ct]=N(x,head[y],z);head[y]=ct;
  25. }
  26. void ps(int x)
  27. {
  28. int nw=am[x].st;
  29. while(fa[nw]!=&&am[x].rest-sid[nw])
  30. {
  31. am[x].rest-=sid[nw];
  32. nw=fa[nw];
  33. }
  34. if(fa[nw]==&&am[x].rest>=*sid[nw])am[x].pos=,am[x].rest-=sid[nw];
  35. else am[x].pos=nw;
  36. }
  37. void init(int x,int f,int g,int w)//fa,gr,lef,sid
  38. {
  39. int t=;
  40. fa[x]=f;sid[x]=w;
  41. if(g==)gr[x]=x;
  42. else gr[x]=g;
  43. for(int i=head[x],u;i;i=edge[i].next)
  44. {
  45. u=edge[i].to;
  46. if(u==f)continue;
  47. init(u,x,gr[x],edge[i].w);t++;
  48. }
  49. if(!t)lef[++lf]=x;
  50. }
  51. void dfs(int x)
  52. {
  53. vis[x]=;
  54. for(int i=head[x],u;i;i=edge[i].next)
  55. if(edge[i].to!=fa[x])dfs(edge[i].to);
  56. }
  57. bool pd(ll mid)
  58. {
  59. // printf("mid=%d\n",mid);
  60. memset(vis,,sizeof vis);
  61. memset(in,,sizeof in);
  62. while(q1.size())q1.pop();
  63. while(q2.size())q2.pop();
  64. for(int i=;i<=m;i++)
  65. {
  66. am[i].rest=mid;
  67. ps(i);
  68. if(am[i].pos!=)dfs(am[i].pos);
  69. q1.push(make_pair(-am[i].rest,i));
  70. }
  71. // for(int i=1;i<=m;i++)
  72. // printf("am[%d].pos=%d\n",i,am[i].pos);
  73. for(int i=;i<=lf;i++)
  74. if(!vis[lef[i]]&&!in[gr[lef[i]]])
  75. {
  76. q2.push(make_pair(-sid[gr[lef[i]]],gr[lef[i]]));
  77. in[gr[lef[i]]]=;
  78. }
  79. // printf("q1:%d q2:%d\n",q1.size(),q2.size());
  80. while(q1.size()&&q2.size())
  81. {
  82. int x=q1.top().second;q1.pop();//am
  83. int y=q2.top().second;q2.pop();//gr
  84. // printf("x=%d y=%d\n",x,y);
  85. while(am[x].rest<sid[gr[y]]&&q1.size())x=q1.top().second,q1.pop();
  86. if(am[x].rest<sid[gr[y]]&&!q1.size())return ;
  87. }
  88.  
  89. if(q2.size())return ;
  90. else return ;
  91. }
  92. int main()
  93. {
  94. scanf("%d",&n);
  95. for(int i=,x,y,z;i<n;i++)
  96. {
  97. scanf("%d%d%d",&x,&y,&z);
  98. add(x,y,z);r+=z;
  99. }
  100. init(,,,);
  101. // for(int i=1;i<=lf;i++)
  102. // printf("lef[%d]=%d\n",i,lef[i]);
  103. scanf("%d",&m);
  104. for(int i=;i<=m;i++)
  105. scanf("%d",&am[i].st);
  106. ans=-;
  107. while(l<=r)
  108. {
  109. ll mid=((l+r)>>);
  110. // cout<<ans<<endl;
  111. if(pd(mid))ans=mid,r=mid-;
  112. else l=mid+;
  113. }
  114. printf("%d",ans);
  115. return ;
  116. }

囧1

这几天又重新写它了,自信码力已和当时不可同日而语,于是又写了一遍,然而仅仅20分,改了改成了30分...

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. #include<queue>
  6. #include<vector>
  7. using namespace std;
  8. typedef long long ll;
  9. int const xn=;
  10. int n,m,cnt,hd[xn],ct,to[xn<<],nxt[xn<<],w[xn<<],rs[xn],lf[xn],rk[xn];
  11. int f[xn][],son[xn],dep[xn],num[xn];
  12. ll dis[xn],sum,ans;
  13. bool vis[xn],use[xn];
  14. priority_queue<int>q;
  15. vector<int>v[xn];
  16. struct N{
  17. int st,pos; ll tim;
  18. bool operator < (const N &y) const
  19. {return tim<y.tim;}
  20. }a[xn];
  21. int rd()
  22. {
  23. int ret=,f=; char ch=getchar();
  24. while(ch<''||ch>''){if(ch=='-')f=; ch=getchar();}
  25. while(ch>=''&&ch<='')ret=(ret<<)+(ret<<)+ch-'',ch=getchar();
  26. return f?ret:-ret;
  27. }
  28. void add(int x,int y,int z){to[++ct]=y; nxt[ct]=hd[x]; w[ct]=z; hd[x]=ct;}
  29. int dfs(int x,int fa,int r)
  30. {
  31. int ret=,fl=; f[x][]=fa;
  32. for(int i=;i<=;i++)f[x][i]=f[f[x][i-]][i-];
  33. for(int i=hd[x],u;i;i=nxt[i])
  34. {
  35. if((u=to[i])==fa)continue;
  36. fl=;
  37. dis[u]=dis[x]+w[i]; dep[u]=dep[x]+;
  38. if(x==)lf[u]+=dfs(u,x,u),son[++cnt]=u;
  39. else ret+=dfs(u,x,r);
  40. }
  41. if(!fl)ret=,rs[x]=r;
  42. return ret;
  43. }
  44. bool cmp(int a,int b){return dis[son[a]]>dis[son[b]];}
  45. void dfs2(int x)
  46. {
  47. bool fl=;
  48. for(int i=hd[x],u;i;i=nxt[i])
  49. if((u=to[i])!=f[x][])fl=,dfs2(u);
  50. if(!fl)num[rs[x]]++;
  51. }
  52. bool ck(int mid)
  53. {
  54. memset(vis,,sizeof vis);
  55. memset(num,,sizeof num);
  56. memset(use,,sizeof use);
  57. for(int i=;i<=cnt;i++)v[i].clear();
  58. while(q.size())q.pop();
  59. for(int i=;i<=m;i++)a[i].pos=;
  60. for(int i=;i<=m;i++)
  61. {
  62. int x=a[i].st; ll ret=mid;
  63. for(int j=;j>=;j--)
  64. if(f[x][j]>&&dis[x]-dis[f[x][j]]<=ret)
  65. ret-=dis[x]-dis[f[x][j]],x=f[x][j];
  66. if(dep[x]>||(dep[x]==&&ret<dis[x]))dfs2(x);
  67. else
  68. {
  69. a[i].pos=x; a[i].tim=ret-dis[x];
  70. q.push(i); //x:1~n
  71. v[x].push_back(i);
  72. // printf("in:%d\n",i);//tim从大到小
  73. }
  74. }
  75. for(int i=;i<=cnt;i++)
  76. if(num[son[i]]==lf[son[i]])vis[i]=;//i != son[i] // vis[1~cnt]
  77. for(int i=;i<=cnt;i++)
  78. {
  79. int x=rk[i];//1~cnt
  80. // printf("vis[%d]=%d\n",son[x],vis[x]);
  81. if(vis[x])continue;
  82. if(!q.size())return ;
  83. int k=q.top(); q.pop();
  84. while(use[k])k=q.top(),q.pop();
  85. if(a[k].tim<dis[son[x]])
  86. {
  87. int us=-;
  88. for(int j=;j<v[son[x]].size();j++)
  89. {
  90. int nw=v[son[x]][j];
  91. if(!use[nw]&&(us==-||a[nw].tim<a[us].tim))us=nw;
  92. }
  93. if(us==-)return ;
  94. else use[us]=,q.push(k);
  95. }
  96. vis[x]=;
  97. // printf("%d -> %d\n",i,son[x]);
  98. }
  99. // printf("return 1\n");
  100. return ;
  101. }
  102. int main()
  103. {
  104. n=rd();
  105. for(int i=,x,y,z;i<n;i++)
  106. {
  107. x=rd(); y=rd(); z=rd();
  108. add(x,y,z); add(y,x,z);
  109. sum+=z;
  110. }
  111. m=rd();
  112. for(int i=;i<=m;i++)a[i].st=rd();
  113. dfs(,,);
  114. for(int i=;i<=cnt;i++)rk[i]=i;
  115. sort(rk+,rk+cnt+,cmp);//rk -> 1~cnt
  116. // for(int i=1;i<=cnt;i++)printf("dis[%d]=%lld rk[%d]=%d\n",son[i],dis[son[i]],i,rk[i]);
  117. ll l=,r=sum; ans=-;
  118. while(l<=r)
  119. {
  120. ll mid=((l+r)>>1ll);
  121. // printf("l=%lld r=%lld mid=%lld\n",l,r,mid);
  122. if(ck(mid))ans=mid,r=mid-;
  123. else l=mid+;
  124. }
  125. printf("%lld\n",ans);
  126. return ;
  127. }

囧2

然后又去参考了TJ...看到思路和我的一样,但是代码简洁很多...

于是改改改,然后和模仿的那篇TJ拍拍拍,居然拍出了TJ的错...又和另一篇TJ拍拍拍,大数据又有错...

不管了直接交上去,就A了...

然后发现数据生成没管军队不在根上,但第一篇TJ小数据真的错了...

和 Narh 的代码拍,大数据又有错...但是数据那么大怎么改...不管了(反正也A了)...

又练习码力了,没事不要多写什么 queue 啦, vector 啦,直接排个序就好了。

代码如下:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. using namespace std;
  6. typedef long long ll;
  7. int const xn=;
  8. int n,m,hd[xn],ct,to[xn<<],nxt[xn<<],w[xn<<],dis[xn],sum,ans;
  9. int f[xn][],num[xn],mn[xn],cnta,cnts,st[xn];
  10. bool vis[xn],use[xn];
  11. struct N{
  12. int id,tim;
  13. bool operator < (const N &y) const
  14. {return tim>y.tim;}
  15. }a[xn],son[xn];
  16. int rd()
  17. {
  18. int ret=,f=; char ch=getchar();
  19. while(ch<''||ch>''){if(ch=='-')f=; ch=getchar();}
  20. while(ch>=''&&ch<='')ret=(ret<<)+(ret<<)+ch-'',ch=getchar();
  21. return f?ret:-ret;
  22. }
  23. void add(int x,int y,int z){to[++ct]=y; nxt[ct]=hd[x]; w[ct]=z; hd[x]=ct;}
  24. void dfs(int x,int fa,int r)
  25. {
  26. int ret=; f[x][]=fa;
  27. for(int i=;i<=;i++)f[x][i]=f[f[x][i-]][i-];
  28. for(int i=hd[x],u;i;i=nxt[i])
  29. {
  30. if((u=to[i])==fa)continue;
  31. dis[u]=dis[x]+w[i]; dfs(u,x,r);
  32. }
  33. }
  34. bool dfs2(int x)
  35. {
  36. bool fl=,bj=;
  37. if(vis[x])return ;
  38. for(int i=hd[x],u;i;i=nxt[i])
  39. {
  40. if((u=to[i])==f[x][])continue; bj=;
  41. bool k=dfs2(u);
  42. if(!k)
  43. {
  44. fl=;
  45. if(x==)son[++cnts].id=u,son[cnts].tim=dis[u];
  46. }
  47. }
  48. if(bj)return ;
  49. return fl;
  50. }
  51. bool ck(int mid)
  52. {
  53. memset(vis,,sizeof vis);
  54. memset(use,,sizeof use);
  55. memset(mn,,sizeof mn);
  56. cnta=; cnts=;
  57. for(int i=;i<=m;i++)
  58. {
  59. int x=st[i]; ll ret=mid;
  60. for(int j=;j>=;j--)
  61. if(f[x][j]>&&dis[x]-dis[f[x][j]]<=ret)
  62. ret-=dis[x]-dis[f[x][j]],x=f[x][j];
  63. if(f[x][]>||(f[x][]==&&ret<dis[x]))vis[x]=;
  64. else
  65. {
  66. a[++cnta].id=i; a[cnta].tim=ret-dis[x];//-dis[x]
  67. if(!mn[x]||a[cnta].tim<a[mn[x]].tim)mn[x]=i;//mn[1~n]=(1~m)
  68. }
  69. }
  70. if(dfs2())return ;
  71. sort(a+,a+cnta+); sort(son+,son+cnts+);
  72. for(int i=,p=;i<=cnts;i++)
  73. {
  74. int nw=son[i].id;
  75. if(mn[nw]&&!use[mn[nw]]){use[mn[nw]]=; continue;}//优先用小的,不用考虑其它儿子是因为从大往小用
  76. while(p<=cnta&&use[a[p].id])p++;
  77. if(p>cnta||a[p].tim<son[i].tim)return ;
  78. use[a[p].id]=;
  79. }
  80. return ;
  81. }
  82. int main()
  83. {
  84. n=rd();
  85. for(int i=,x,y,z;i<n;i++)
  86. {
  87. x=rd(); y=rd(); z=rd();
  88. add(x,y,z); add(y,x,z);
  89. sum+=z;
  90. }
  91. m=rd();
  92. for(int i=;i<=m;i++)st[i]=rd();
  93. dfs(,,);
  94. int l=,r=sum; ans=-;
  95. while(l<=r)
  96. {
  97. int mid=((l+r)>>1ll);
  98. if(ck(mid))ans=mid,r=mid-;
  99. else l=mid+;
  100. }
  101. printf("%d\n",ans);
  102. return ;
  103. }

洛谷 P1084 疫情控制 —— 二分+码力的更多相关文章

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

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

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

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

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

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

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

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

  5. NOIP2012 洛谷P1084 疫情控制

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

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

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

  7. 洛谷P1084 疫情控制

    题目 细节比较多的二分+跟LCA倍增差不多的思想 首先有这样一个贪心思路,深度越低的检查点越好,而最长时间和深度具有单调性,即给定时间越长,每个军队能向更浅的地方放置检查点.因此可以考虑二分时间,然后 ...

  8. Luogu P1084 疫情控制 | 二分答案 贪心

    题目链接 观察题目,答案明显具有单调性. 因为如果用$x$小时能够控制疫情,那么用$(x+1)$小时也一定能控制疫情. 由此想到二分答案,将问题转换为判断用$x$小时是否能控制疫情. 对于那些在$x$ ...

  9. luogu P1084疫情控制 二分

    链接 loj luogu太水不要去了. 思路 二分. 每个军队在一定的时间内越往上越好. 注意一个军队可以跨过1去帮别的. 把能到1脚下的点都存下来特判. 有一种情况是这个子树内只有一个军队,但这个军 ...

随机推荐

  1. win10下硬盘安装CentOS7

    安装环境: 1.系统:Windows 10 2.硬盘:SSD(已装好Win 10) + HHD(用来装CentOS 7) 准备工作: 1.DiskGenius(分区工具):用来给硬盘做分区: 2.系统 ...

  2. package control(转载)

    Package Control(扩展包管理器)   []Package Control 可以看做是一个ST的扩展管理器,可以去下载.安装.删除 Sublime Text 3的各种插件.皮肤等.   [ ...

  3. 582. Kill Process

    Problem statement: Given n processes, each process has a unique PID (process id) and its PPID (paren ...

  4. 可并堆试水--BZOJ1367: [Baltic2004]sequence

    n<=1e6个数,把他们修改成递增序列需把每个数增加或减少的总量最小是多少? 方法一:可以证明最后修改的每个数一定是原序列中的数!于是$n^2$DP(逃) 方法二:把$A_i$改成$A_i-i$ ...

  5. Linux下汇编语言学习笔记52 ---

    这是17年暑假学习Linux汇编语言的笔记记录,参考书目为清华大学出版社 Jeff Duntemann著 梁晓辉译<汇编语言基于Linux环境>的书,喜欢看原版书的同学可以看<Ass ...

  6. pandas中计算总体标准差

    标准差(或方差),分为 总体标准差(方差)和 样本标准差(方差). 前者分母为n,后者为n-1.后者是无偏的. pandas里的 .std() 和 .var() 都是算的无偏的. 而numpy是有偏的 ...

  7. Just a Hook-HDU1698(线段树求区间)

    http://acm.hdu.edu.cn/showproblem.php?pid=1698 Problem Description In the game of DotA, Pudge’s meat ...

  8. 洛谷 P1318 积水面积

    P1318 积水面积 题目描述 一组正整数,分别表示由正方体迭起的柱子的高度.若某高度值为x,表示由x个正立方的方块迭起(如下图,0<=x<=5000).找出所有可能积水的地方(图中蓝色部 ...

  9. Android GIS开发系列-- 入门季(13)Gdal简单写个shp文件

    Gdal是用来读写栅格与矢量数据的,在Gdal官网,可以下载相关的资源进行平台的编译.其实Arcgis底层也是用Gdal来读取shp文件的,那在Android中可以直接读写shp文件吗,是可以的.这里 ...

  10. 实战!利用MSF批量扫描校园网中含有MS17_010漏洞的主机并入侵

    利用ms17_010的永恒之蓝在前些日子火爆了一段时间,校园网中也声称封锁了相应端口.最近在搞MSF的深入学习,于是有了下文. ms17_010扫描工具 msf中的辅助模块含有一个强大的ms17_01 ...