NOIP2012 D2T3 疫情控制 题解
这道题由于问最大值最小,所以很容易想到二分,但怎么验证并且如何实现是这道题的难点;
首先我们考虑,对于一个军队,尽可能的往根节点走(但一定不到)是最优的;
判断一个军队最远走到哪可以树上倍增来实现;
但是,这并没有结束,因为可能这颗子树的军队会去另一个军队;
我们先找出所有以根节点的子节点为根的子树中,是否有到叶子节点的路径还未被驻扎,并记录下还有路径未被驻扎的这些子树的根节点;
若该节点上停留有军队,则剩余时间最小的军队驻扎在该节点一定是最优的。
这样处理过这些节点后,把剩下的节点按照到根节点的距离从小到大排序。
对于现在闲置的军队和需要被驻扎的节点,让剩余时间小的军队优先驻扎在距离根节点近的节点,这样可以保证决策最优
#include <bits/stdc++.h>
using namespace std;
const int MXR=5e4+2;
int n,m,t,tot=0,atot=0,btot=0,ctot=0;
int d[MXR],query[MXR],f[MXR][20];
int ver[2*MXR],edge[2*MXR],MXRext[2*MXR],head[MXR],dist[MXR][20];
pair<long long,int> h[MXR];
void add(int x,int y,int z){
ver[++tot]=y,edge[tot]=z,MXRext[tot]=head[x],head[x]=tot;
}
void bfs()
{
queue<int> q;
q.push(1);
d[1]=1;
while(q.size()){
int x=q.front();q.pop();
for(int i=head[x];i;i=MXRext[i]){
int y=ver[i];
if(d[y]) continue;
d[y]=d[x]+1;
f[y][0]=x,dist[y][0]=edge[i];
for(int j=1;j<=t;j++){
f[y][j]=f[f[y][j-1]][j-1];
dist[y][j]=dist[y][j-1]+dist[f[y][j-1]][j-1];
}
q.push(y);
}
}
}
bool ok,sta[MXR],need[MXR];
long long ans,tim[MXR],ned[MXR];
int dfs(register int x)
{
bool pson=0;
if(sta[x]) return 1;
for(int i=head[x];i;i=MXRext[i]){
int y=ver[i];
if(d[y]<d[x]) continue;
pson=1;
if(!dfs(y)) return 0;
}
if(!pson) return 0;
return 1;
}
template<class nT>
inline void read(nT&x)
{
char c;while(c=getchar(),!isdigit(c));
x=c^48;while(c=getchar(),isdigit(c)) x=x*10+c-48;
}
bool check(long long lim)
{
memset(sta,0,sizeof(sta));
memset(tim,0,sizeof(tim));
memset(ned,0,sizeof(ned));
memset(h,0,sizeof(h));
memset(need,0,sizeof(need));
atot=0,btot=0,ctot=0;
for(int i=1;i<=m;i++){
long long x=query[i],cnt=0;
for(int j=t;j>=0;j--)
if(f[x][j]>1 && cnt+dist[x][j]<=lim){
cnt+=dist[x][j];
x=f[x][j];
}
if(f[x][0]==1 && cnt+dist[x][0]<=lim) h[++ctot]=make_pair(lim-cnt-dist[x][0],x);
else sta[x]=1;
}
for(int i=head[1];i;i=MXRext[i]) if(!dfs(ver[i])) need[ver[i]]=1;
sort(h+1,h+ctot+1);
for(int i=1;i<=ctot;i++){
if(need[h[i].second] && h[i].first<dist[h[i].second][0]) need[h[i].second]=0;
else tim[++atot]=h[i].first;
}
for(int i=head[1];i;i=MXRext[i]) if(need[ver[i]]) ned[++btot]=dist[ver[i]][0];
if(atot<btot) return 0;
sort(tim+1,tim+atot+1),sort(ned+1,ned+btot+1);
int i=1,j=1;
while(i<=btot && j<=atot)
if(tim[j]>=ned[i]){
i++,j++;
}
else j++;
if(i>btot)return 1;
return 0;
}
int main()
{
long long l=0,r=0,mid;
cin>>n;
t=log2(n)+1;
for(int i=1;i<=n-1;i++){
int x,y,z;
read(x); read(y); read(z);
add(x,y,z),add(y,x,z);
r+=z;
}
bfs();
cin>>m;
for(int i=1;i<=m;i++) read(query[i]);
while(l<=r){
mid=(l+r)>>1;
if(check(mid)){
r=mid-1;
ans=mid;
ok=1;
}
else
l=mid+1;
}
if(!ok) cout<<-1;
else cout<<ans;
return 0;
}
NOIP2012 D2T3 疫情控制 题解的更多相关文章
- NOIP2012 疫情控制 题解(LuoguP1084)
NOIP2012 疫情控制 题解(LuoguP1084) 不难发现,如果一个点向上移动一定能控制更多的点,所以可以二分时间,判断是否可行. 但根节点不能不能控制,存在以当前时间可以走到根节点的点,可使 ...
- 【NOIP2012】 疫情控制
[NOIP2012] 疫情控制 标签: 倍增 贪心 二分答案 NOIP Description H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树, 1 号城市是首都, 也是 ...
- luoguP1084 疫情控制(题解)(搜索+贪心)
luoguP1084 疫情控制 题目 #include<iostream> #include<cstdlib> #include<cstdio> #include& ...
- [NOIp2012]疫情控制 题解
好久没更,强迫自己写一篇. 神 tm 大预言家出的题 注意到如果 \(x\) 小时可以控制住疫情,则 \(\forall x'>x\) 必然也可以控制住疫情,显然答案具有单调性,可以二分答案. ...
- noip2012疫情控制 题解
题目大意 给出一棵n个节点的树,根是1,要在除根节点以外的点建立检查点,使得从每条根到叶子的路径上都至少存在一个检查点.检查点由军队来建立.初始军队的位置是给定的,移动军队走一条边需要花费这条边的权值 ...
- [LOJ2607]【NOIP2012】疫情控制
题意: 题目描述 H 国有n个城市,这n个城市用n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边 ...
- 【noip2012】疫情控制
题意: 给出一颗n个节点有边权的树 和m个军队所在的位置 军队从某节点移动到相邻节点要花费边长度的时间 求最少要多少时间使得根节点(编号为1)到每个叶子的路径上最少有一支军队(根节点不能有军队) 题解 ...
- 【NOIP2012】疫情控制(二分,倍增,贪心)
洛谷上的题目链接,题目不在赘述 题解 既然要时间最短,首先考虑二分. 因此,考虑二分时间,问题转换为如何检查能否到达. 如果一支军队一直向上走,能够到达根节点,那么他可以通过根节点到达其他的节点,因此 ...
- [NOIP2012]疫情控制 贪心 二分
题面:[NOIP2012]疫情控制 题解: 大体思路很好想,但是有个细节很难想QAQ 首先要求最大时间最小,这种一般都是二分,于是我们二分一个时间,得到一个log. 然后发现一个军队,越往上走肯定可以 ...
随机推荐
- Visualizing and Understanding Convolutional Networks
前言:研究卷积神经网络,把阅读到的一些文献经典的部分翻译一下,写成博客,代码后续给出,不足之处还请大家指出. 本文来自:tony-tan.com Github:github.com/Tony-Tan ...
- websocket 连接测试端口服务是否正常代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 9030PCI CAN驱动开发点滴
1.配置EEPROM. 使用PlxMon打开9030,基本修改Spacex(0,1,2,3), Chip selectx(0,1,2,3), 中断状态INTCSR(0x74), 其他(0x78),详细 ...
- Ubuntu下的redis安装过程
Redis make test Errors? - Stack Overflow https://stackoverflow.com/questions/48425998/redis-make-te ...
- 树状数组(BIT)
树状数组 树状数组是在线段树的结构上改造而来数据结构,主要用于完成: 给定一个初始值全为0的数列 ①给定i,计算返回a1+a2+--+ai的值 ②给定i和x,执行ai+=x BIT的求和 ll sum ...
- [洛谷P3941]:入阵曲(前缀和+桶)
题目传送门 题目背景 丹青千秋酿,一醉解愁肠.无悔少年枉,只愿壮志狂. 题目描述 小$F$很喜欢数学,但是到了高中以后数学总是考不好.有一天,他在数学课上发起了呆:他想起了过去的一年.一年前,当他初识 ...
- leetcode题目17.电话号码的字母组合(中等)
题目描述: 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合. 给出数字到字母的映射如下(与电话按键相同).注意 1 不对应任何字母. 示例: 输入:"23"输出: ...
- C++ 编程风格指南
C++ Programming Style Guidelines 他人翻译中文版:click 让程序具有好的可读性 “避免日后 有人(或者自己)指着你的代码骂娘:这特么谁写的破烂 玩意”(来自:知乎- ...
- window 下要运行php,需要编辑php环境变量
参考:https://blog.csdn.net/zhezhebie/article/details/72765262
- laravel 文件上传总结
调用 store 方法会生成唯一的 ID 来作为文件名,如果想获取原件本来的名称可以使用 $file = $request->file('file'); $file->getClientO ...