因为若一个时间限制满足题意,则所有比它大的时间限制一定都满足题意,因此本题答案具有单调性,可以想到二分答案求解。

本题思路不是很难,但细节和代码实现比较复杂。

见牛人博客: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 提高组] 疫情控制 (二分答案、贪心)的更多相关文章

  1. [NOIP2012提高组]疫情控制

    题目:洛谷P1084.codevs1218.Vijos P1783. 题目大意:有一棵n个节点的,根为1的带权树和m支军队.每支军队可以在一个点上停下,那么从1开始就不能经过这个点了.现在有m支军队已 ...

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

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

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

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

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

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

  5. Luogu1084 NOIP2012D2T3 疫情控制 二分答案、搜索、贪心、倍增

    题目传送门 题意太长就不给了 发现答案具有单调性(额外的时间不会对答案造成影响),故考虑二分答案. 贪心地想,在二分了一个时间之后,军队尽量往上走更好.所以我们预处理倍增数组,在二分时间之后通过倍增看 ...

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

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

  7. 刷题总结——疫情控制(NOIP2012提高组)

    题目: 题目背景 NOIP2012 提高组 DAY2 试题. 题目描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点. H 国的首都 ...

  8. GZOJ 1361. 国王游戏【NOIP2012提高组DAY1】

    国王游戏[NOIP2012提高组DAY1] Time Limit:1000MS Memory Limit:128000K Description 国王游戏(game.cpp/c/pas) [问题描述] ...

  9. BZOJ_2196_[Usaco2011 Mar]Brownie Slicing_二分答案+贪心

    BZOJ_2196_[Usaco2011 Mar]Brownie Slicing_二分答案+贪心 Description Bessie烘焙了一块巧克力蛋糕.这块蛋糕是由R*C(1 <= R,C ...

随机推荐

  1. IM系统-消息流化一些常见问题

    原创不易,求分享.求一键三连 之前说过IM系统的一些优化,但是在网络上传输数据对于数据的流化和反流化也是处理异常情况的重点环节,不处理好可能会出现一些消息发送成功,但是解析失败的情况,本文就带大家来一 ...

  2. 循环结构——while、do-while、for循环

    1.while循环 语法格式: while(条件判断){ 循环体 } 解释: (1)关键字while后的小括号中的内容时循环条件. (2)循环条件是一个布尔表达式,它的值为布尔类型 "真&q ...

  3. 漂亮简洁的PHP导航源码-蘑菇导航

    蘑菇导航 蘑菇导航是根据SimpleWebNavigation修改而来的一个php网址导航.支持php8,支持左侧锚点,支持自定义fontawesome图标. 可以作为群组导航.图床导航.vps导航等 ...

  4. rh358 002 fact变量获取 ansible配置网络 service_facts

    通过ansible 获取网络信息 1.如何获取fact事实变量 方式1: ansible servera -m servera 方式2: 剧本 [root@workstation ansible]# ...

  5. 从原理剖析带你理解Stream

    摘要:Stream是jdk1.8给我们提供的新特性 本文分享自华为云社区<深入理解Stream之原理剖析>,作者: 李哥技术 . Stream是jdk1.8给我们提供的新特性,主要就是允许 ...

  6. 开发个RTMP播放器居然这么难?RTMP播放器对标和考察指标

    好多开发者提到,RTMP播放器,不知道有哪些对标和考察指标,以下大概聊聊我们的一点经验,感兴趣的,可以关注 github: 1. 低延迟:大多数RTMP的播放都面向直播场景,如果延迟过大,严重影响体验 ...

  7. 洛谷P7112 行列式求值

    行列式求值 这是一个让你掉头发的模板题 行列式的定义 行列式 (\(\texttt{Determinant}\)) 是一个函数定义,取值是一个标量. 对一个 \(n\times n\) 的矩阵 \(A ...

  8. MySQL 中的锁机制

    介绍锁机制 技术是为了解决问题而生的,锁被用来实现隔离性,保证并发事务的正确性. 两段锁 & 一次封锁 两段锁 数据库遵循的是两段锁协议,将事务分成两个阶段,加锁阶段和解锁阶段(所以叫两段锁) ...

  9. SQL语句中过滤条件放在on和where子句中的区别和联系

    摘要: 介绍在多表关联SQL语句中,过滤条件放在on和where子句中的区别--inner join中没区别,外连接就不一样. 综述   蚂蚁金服的一道SQL面试题如下:SQL语句中,过滤条件放在on ...

  10. js 数组中的方法

    <!DOCTYPE html><html><head> <title>数组的方法</title> <meta charset=&quo ...