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

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

见牛人博客: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. go更新腾讯云DNSPod的解析记录

    纯粹练手用的,大家轻喷 获取SecretId,SecretKey 打开腾讯云,登录之后打开https://console.cloud.tencent.com/cam/capi,然后新建密钥记录生成的S ...

  2. 并发编程原理学习-reentrantlock源码分析

    ReentrantLock基本概念 ​ ReentrantLock是一个可重入锁,顾名思义,就是支持重进入的锁,它表示该锁能够支持一个线程对资源的重复加锁,并且在获取锁时支持选择公平模式或者非公平模式 ...

  3. Dapr学习(4)之eShopOnDapr部署(Rancher2.63&k3s)

    本篇主要讲述一下github上基于Dapr实现的商城demo在(K8s or K3s)环境中的部署实践,本文环境基于k3s&rancher2.6.3 1.eShopOnDapr源代码及概述 源 ...

  4. Taurus.MVC WebAPI 入门开发教程4:控制器方法及参数定义、获取及基础校验属性【Require】。

    系列目录 1.Taurus.MVC WebAPI  入门开发教程1:框架下载环境配置与运行. 2.Taurus.MVC WebAPI 入门开发教程2:添加控制器输出Hello World. 3.Tau ...

  5. 使用xshell linux安装nodejs,CentOS下安装并配置nodejs环境教程

    1. 下载node最新版本 : 连接   https://nodejs.org/zh-cn/(查看node最新版本) 在跟目录root下,命令行输入: wget https://nodejs.org/ ...

  6. 【常见】CSS3进度条Loading动画

    现在,GIF 格式的进度条已经越来越少,CSS 进度条如雨后春笋般涌现.CSS3的崛起,更使得动态效果得以轻松实现,未来,必定是CSS3的天下,所以今天我就来分享一下几个常见的CSS3进度条Loadi ...

  7. iommu系列之---概念解释篇

    本文会对iommu中的一些容易引起疑惑的概念进行阐述,内核版本为4.19. 先上简写: DMAR - DMA remapping DRHD - DMA Remapping Hardware Unit ...

  8. oracle 怎么查看用户对应的表空间

    oracle 怎么查看用户对应的表空间? 查询用户: 查看数据库里面所有用户,前提是你是有 dba 权限的帐号,如 sys,system: select * from dba_users; 查看你能管 ...

  9. 事物的隔离性和MVCC

    事物的隔离性 mysql的服务端是支持多个客户端同时与之连接的,每个客户端可能还并发了好几个连接,所以mysql是需要同时处理很多事情的,每一件独立的事情就叫做事务.我们知道事务有一个叫隔离性的特性, ...

  10. 最短路径算法-迪杰斯特拉(Dijkstra)算法在c#中的实现和生产应用

    迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先遍历思想),直到扩展到终点为止 贪心算法(Greedy ...