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. 然后发现一个军队,越往上走肯定可以 ...
随机推荐
- Java中indexOf的用法
indexOf有四种用法: 1.indexOf(int ch) 在给定字符串中查找字符(ASCII),找到返回字符数组所对应的下标找不到返回-1 2.indexOf(String str)在给定符串中 ...
- go之基本数据类型
一.整形 Go语言里支持有符号和无符号两种整型.这里的符号就是正负号. 1.分类: 有符号的整型:int , int8 , int16 , int32 , int64 无符号的整型:uint,uint ...
- Linux-配置共享目录
找到相关rpm包 运行以及错误解决** rpm -ivh tcp_wrappers-7.6-34.i386.rpm rpm -ivh portmap-4.0-54.i386.rpm rpm -ivh ...
- $\LaTeX$数学公式大全3
$3\ Delimiters$$|$ |$\vert$ \vert$\|$ \|$\Vert$ \Vert$\{$ \{$\}$ \}$\langle$ \langle$\rangle$ \rangl ...
- linux rpm包管理 yum管理
1. 软件包的管理 RPM的定义:RPM就是Red Hat Package Manger(红帽软件包管理工具)的缩写. RPM包不需要编译,本身就是二进制,而源码包需要先编译成系统识别的二进制文件,才 ...
- TCP输入 之 tcp_v4_rcv
tcp_v4_rcv函数为TCP的总入口,数据包从IP层传递上来,进入该函数:其协议操作函数结构如下所示,其中handler即为IP层向TCP传递数据包的回调函数,设置为tcp_v4_rcv: sta ...
- 转自网络用LIBSVM进行回归预测的粗浅认识————————作者师梦
说一说我对用LIBSVM进行回归预测的粗浅认识(整理完成于2012年5.11) 作者 : 师梦 吾本工程小硕一枚,前用matlab建模,已然完成.某日,正沾沾自喜之际,吾师曰:“汝已为之 ...
- mysql之备份与恢复
数据备份全备 备份命令 :mysqldump把数据库的数据以sql语句导出属于逻辑备份 格式 : mysqldump -uroot -p123456 -S 多实例的mysql.sock 数据库名 &g ...
- Class 源码解读
Class 获取包信息 /** * 获取此对象所在的包 * @revised 9 * @spec JPMS */ public Package getPackage() { // 原始类型和数组无 P ...
- Python:目录
ylbtech-Python:目录 1.返回顶部 2.返回顶部 3.返回顶部 4.返回顶部 5.返回顶部 6.返回顶部 作者:ylbtech出处:http://ylbtec ...