P1084 [NOIP2012 提高组] 疫情控制 (二分答案、贪心)
因为若一个时间限制满足题意,则所有比它大的时间限制一定都满足题意,因此本题答案具有单调性,可以想到二分答案求解。
本题思路不是很难,但细节和代码实现比较复杂。
见牛人博客:https://www.luogu.com.cn/blog/TEoS/p1084-yi-qing-kong-zhi
1 #include<bits/stdc++.h>
2 typedef long long ll;
3 using namespace std;
4 const int N=6e4;
5 int n,m,t,tot,atot,btot,ctot;
6 int d[N],query[N],f[N][20];
7 int to[N<<1],edge[N<<1],nxt[N<<1],head[N];
8 bool ok,sta[N],need[N];
9 ll ans,tim[N],ned[N],dist[N][20];
10 pair<ll,int> h[N];
11 queue<int> q;
12 void add(int x,int y,int z){
13 nxt[++tot]=head[x];head[x]=tot;to[tot]=y;edge[tot]=z;
14 }
15
16 void bfs(){
17 q.push(1);d[1]=1;
18 while(q.size()){
19 int x=q.front();q.pop();
20 for(int i=head[x];i;i=nxt[i]){
21 int y=to[i];
22 if(d[y]) continue;
23 d[y]=d[x]+1;
24 f[y][0]=x;dist[y][0]=edge[i];
25 for(int j=1;j<=t;j++){
26 f[y][j]=f[f[y][j-1]][j-1];
27 dist[y][j]=dist[y][j-1]+dist[f[y][j-1]][j-1];
28 }
29 q.push(y);
30 }
31 }
32 }
33
34 void init(){
35 memset(sta,0,sizeof(sta));
36 memset(tim,0,sizeof(tim));
37 memset(ned,0,sizeof(ned));
38 memset(h,0,sizeof(h));
39 memset(need,0,sizeof(need));
40 atot=0,btot=0,ctot=0;
41 }
42
43 bool dfs(int x){
44 bool pson=0;
45 if(sta[x]) return 1;
46 for(int i=head[x];i;i=nxt[i]){
47 int y=to[i];
48 if(d[y]<d[x]) continue;
49 pson=1;
50 if(!dfs(y)) return 0;
51 }
52 if(!pson) return 0;
53 return 1;
54 }//如果是叶子结点,pson=0,那么该路径没有军队驻扎
55
56 bool ck(ll lim){
57 for(int i=1;i<=m;i++){//上移军队并处理闲置军队
58 ll x=query[i],cnt=0;
59 for(int j=t;j>=0;j--)
60 if(f[x][j]>1/*不能是根节点*/ && cnt+dist[x][j]<=lim){
61 cnt+=dist[x][j];
62 x=f[x][j];
63 }
64 if(f[x][0]==1 && cnt+dist[x][0]<=lim)
65 h[++ctot]=make_pair(lim-cnt-dist[x][0],x);
66 else sta[x]=1;
67 }
68 for(int i=head[1];i;i=nxt[i])
69 if(!dfs(to[i])) need[to[i]]=1;//dfs寻找路径未被驻扎的叶子节点
70 sort(h+1,h+ctot+1);//第一关键字排序
71 for(int i=1;i<=ctot;i++)
72 if(need[h[i].second] && h[i].first<dist[h[i].second][0])
73 need[h[i].second]=0;
74 else tim[++atot]=h[i].first;//对根节点的需要被驻扎的子节点进行初步处理
75 for(int i=head[1];i;i=nxt[i])
76 if(need[to[i]]) ned[++btot]=dist[to[i]][0];//找到仍需要被驻扎的节点并存储
77 if(atot<btot) return 0;//无解
78 sort(ned+1,ned+btot+1);
79 int i=1,j=1;
80 while(i<=btot && j<=atot)//双指针扫描
81 if(tim[j]>=ned[i]) i++,j++;
82 else j++;
83 if(i>btot) return 1;
84 return 0;
85 }
86
87 int main(){
88 cin>>n;ll l=0,r=0,mid;
89 t=log2(n)+1;
90 for(int i=1;i<n;i++){
91 int x,y,z;scanf("%d%d%d",&x,&y,&z);
92 add(x,y,z);add(y,x,z);r+=z;
93 }
94 bfs();//树上倍增预处理
95 cin>>m;for(int i=1;i<=m;i++) scanf("%d",&query[i]);//存每个军队
96 while(l<=r){//二分答案
97 init();mid=(l+r)>>1;
98 if(ck(mid)) r=mid-1,ans=mid,ok=1;
99 else l=mid+1;
100 }
101 if(!ok) cout<<-1<<endl;
102 else cout<<ans<<endl;
103 return 0;
104 }
P1084 [NOIP2012 提高组] 疫情控制 (二分答案、贪心)的更多相关文章
- [NOIP2012提高组]疫情控制
题目:洛谷P1084.codevs1218.Vijos P1783. 题目大意:有一棵n个节点的,根为1的带权树和m支军队.每支军队可以在一个点上停下,那么从1开始就不能经过这个点了.现在有m支军队已 ...
- Luogu P1084 疫情控制 | 二分答案 贪心
题目链接 观察题目,答案明显具有单调性. 因为如果用$x$小时能够控制疫情,那么用$(x+1)$小时也一定能控制疫情. 由此想到二分答案,将问题转换为判断用$x$小时是否能控制疫情. 对于那些在$x$ ...
- 洛谷P1084 [NOIP2012提高组Day2T3]疫情控制
P1084 疫情控制 题目描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控 ...
- NOIP2012疫情控制(二分答案+树上贪心)
H 国有n个城市,这 n个城市用n-1条双向道路相互连通构成一棵树,1号城市是首都,也是树中的根节点. H国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边境城市(叶子节点所表示 ...
- Luogu1084 NOIP2012D2T3 疫情控制 二分答案、搜索、贪心、倍增
题目传送门 题意太长就不给了 发现答案具有单调性(额外的时间不会对答案造成影响),故考虑二分答案. 贪心地想,在二分了一个时间之后,军队尽量往上走更好.所以我们预处理倍增数组,在二分时间之后通过倍增看 ...
- luogu1084 [NOIp2012]疫情控制 (二分答案+倍增+dfs序)
先二分出一个时间,把每个军队倍增往上跳到不能再跳 然后如果它能到1号点,就记下来它跳到1号点后剩余的时间:如果不能,就让它就地扎根,记一记它覆盖了哪些叶节点(我在这里用了dfs序+差分,其实直接dfs ...
- 刷题总结——疫情控制(NOIP2012提高组)
题目: 题目背景 NOIP2012 提高组 DAY2 试题. 题目描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点. H 国的首都 ...
- GZOJ 1361. 国王游戏【NOIP2012提高组DAY1】
国王游戏[NOIP2012提高组DAY1] Time Limit:1000MS Memory Limit:128000K Description 国王游戏(game.cpp/c/pas) [问题描述] ...
- BZOJ_2196_[Usaco2011 Mar]Brownie Slicing_二分答案+贪心
BZOJ_2196_[Usaco2011 Mar]Brownie Slicing_二分答案+贪心 Description Bessie烘焙了一块巧克力蛋糕.这块蛋糕是由R*C(1 <= R,C ...
随机推荐
- 使用centos linux vps搭建jupyter notebook踩坑日记
今天我尝试用vps搭建在线jupyter notebook网站时遇到了这样一个问题: [W 21:48:07.243 NotebookApp] SSL Error on 9 ('171.115.101 ...
- 面试题:Java中为什么只有值传递?
作者:小牛呼噜噜 | https://xiaoniuhululu.com 计算机内功.JAVA底层.面试相关资料等更多精彩文章在公众号「小牛呼噜噜 」 目录 经典的问题 形参&实参 Java是 ...
- 停止、启动nginx以及在windows下使用dos命令停止占用的端口
windows下使用dos命令查看占用端口号并停止 windows+R打开命令窗口 查找占用端口对应的PID(进程号) netstat -ano|findstr "port" # ...
- MySQL表操作过程的基础代码解析
GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. MySQL 的表有很多种,对表的操作主要是增删改查,今天来浅谈一下这些操作的底层代码和流程,以下以 tmp table为例 ...
- 飞书前端提到的竞态问题,在 Android 上怎么解决?
请点赞关注,你的支持对我意义重大. Hi,我是小彭.本文已收录到 GitHub · AndroidFamily 中.这里有 Android 进阶成长知识体系,有志同道合的朋友,关注公众号 [彭旭锐] ...
- LuoguP5322 [BJOI2019]排兵布阵(DP)
城为物,人为容,价值?排序后,一切都明了 #include <iostream> #include <cstdio> #include <cstring> #inc ...
- z—libirary最新地址获取,zlibirary地址获取方式,zliabary最新地址,zliabary官网登录方式,zliabary最新登陆
Z-Library(缩写为z-lib,以前称为BookFinder)是Library Genesis的镜像,一个影子图书馆项目,用于对学术期刊文章.学术文本和大众感兴趣的书籍(其中一些是盗版的)进行文 ...
- Python自学教程12-类和对象怎么用
Python是一门现代化的编程语言,也是一门面向对象的编程语言. 现代编程语言几乎都支持面向对象编程,面向对象编程是最有效的软件编写方法之一.你可以用类和对象来表示现实当中的任何的事物和行为. 编写类 ...
- React的生命周期函数
概述 在React中,生命周期函数指的是组件在某一个时刻会自动执行的函数 constructor 在类或组件创建的时候被自动执行,我们可以说它是生命周期函数,但它并不是React所特有的,所有的Es6 ...
- Springboot连接数据库 (解决报错)
好家伙,来解决报错 1.新建项目时, 将SQL的" Spring Date 'jdbc' "点上 2.使用idea快速创建springboot项目时会出现连接不到服务器的情况 这里 ...