【NOIP2012】 疫情控制

标签: 倍增 贪心 二分答案 NOIP


Description

H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树, 1 号城市是首都, 也是树中的根节点。

H 国的首都爆发了一种危害性极高的传染病。当局为了控制疫情,不让疫情扩散到边境 城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从首都到边境 城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点。但特别要注意的是, 首都是不能建立检查点的。

现在,在 H 国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队。一支军队可以在有道路连接的城市间移动,并在除首都以外的任意一个城市建立检查点,且只能在 一个城市建立检查点。一支军队经过一条道路从一个城市移动到另一个城市所需要的时间等 于道路的长度(单位:小时)。

请问最少需要多少个小时才能控制疫情。注意:不同的军队可以同时移动。

Input

第一行一个整数 n,表示城市个数。

接下来的 n-1 行,每行 3 个整数,u、v、w,每两个整数之间用一个空格隔开,表示从 城市 u 到城市 v 有一条长为 w 的道路。数据保证输入的是一棵树,且根节点编号为 1。

接下来一行一个整数 m,表示军队个数。

接下来一行 m 个整数,每两个整数之间用一个空格隔开,分别表示这 m 个军队所驻扎 的城市的编号。

Output

共一行,包含一个整数,表示控制疫情所需要的最少时间。如果无法控制疫情则输出-1。

Sample Input

4

1 2 1

1 3 2

3 4 3

2

2 2

Sample Output

3

Hint

样例说明:

第一支军队在 2 号点设立检查点,第二支军队从 2 号点移动到 3 号点设立检查点,所需 时间为 3 个小时。

【数据范围】

保证军队不会驻扎在首都。

对于 20%的数据,2≤ n≤ 10;

对于 40%的数据,2 ≤n≤50,0<w <10^5;

对于 60%的数据,2 ≤ n≤1000,0<w <10^6;

对于 80%的数据,2 ≤ n≤10,000;

对于 100%的数据,2≤m≤n≤50,000,0<w <10^9


题意

大概意思就是给你n个军队(在不同的城市),你要移动他们到节点上(非根节点)来隔断根节点与每个叶子节点,求移动军队时间的最小值(两个不同的军队可以同时移动)。


题解

  • 首先,移动军队的时间肯定是越多越好,肯定是满足单调性的,我们很容易想到用二分答案来做。
  • 当我们二分答案x之后,我们应该思考军队往哪里走更好,显然是要往上走的,因为每往上走,就能覆盖更大的子树。
  • 对于往上走,我们分两种情况讨论
    1. 如果该军队没有到达根节点,那么我们不用管他,直接让他在这个节点。
    2. 如果该军队到了根节点,那么我们就可以把这个军队往下走一步,来覆盖其他节点。
  • 我们只要把军队还剩下的移动距离和每被覆盖的深度为2的点分别排序,然后扫一遍就行了。
  • 真的这么简单吗?显然不是。如果这么做的话,你会发现样例都过不了。
  • 因为即使某个军队到了根节点,他可能不如只到根节点之前的那个点优秀(因为他可能回不去了),那么我们只需要把回不去的军队弄回去就行了。
  • 对于这个结论其实很好证明:假设该军队为A,他之前的那个点为lst(A),现在他不回去,而选择另外一个点b,去他之前的那个点的军队为B,那么val (A)<val(B),就不如A回去,B再到另外的点。

Code

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define REP(i,a,b) for(int i=(a),_end_=(b);i<=_end_;i++)
#define DREP(i,a,b) for(int i=(a),_end_=(b);i>=_end_;i--)
#define EREP(i,a) for(int i=start[(a)];i;i=e[i].next)
inline int read()
{
int sum=0,p=1;char ch=getchar();
while(!(('0'<=ch && ch<='9') || ch=='-'))ch=getchar();
if(ch=='-')p=-1,ch=getchar();
while('0'<=ch && ch<='9')sum=sum*10+ch-48,ch=getchar();
return sum*p;
} const int maxn=5e5+20; struct node {
int v,next,w;
};
node e[maxn*2];
int n,m;
int start[maxn],cnt; void addedge(int u,int v,int w)
{
e[++cnt]={v,start[u],w};
start[u]=cnt;
} int p[maxn][17],pw[maxn][17],deep[maxn],vis[maxn],st[maxn]; void dfs(int u,int fa)
{
deep[u]=deep[fa]+1;p[u][0]=fa;
EREP(i,u)
{
int v=e[i].v;
if(v==fa)continue;
pw[v][0]=e[i].w;
dfs(v,u);
} } int Sum=0; void init()
{
n=read();
REP(i,1,n-1)
{
int u=read(),v=read(),w=read();
addedge(u,v,w);Sum+=w;
addedge(v,u,w);
}
dfs(1,0);
for(int j=1;(1<<j)<=n;j++)
{
REP(i,1,n)
p[i][j]=p[p[i][j-1]][j-1],pw[i][j]=pw[i][j-1]+pw[p[i][j-1]][j-1];
}
m=read();
REP(i,1,m)st[i]=read();
} bool dfs1(int u,int fa)
{
if(vis[u])return true;
bool flag=false;
EREP(i,u)
{
int v=e[i].v;
if(v==fa)continue;
flag=true;
if(!dfs1(v,u))return false;
}
vis[u]=flag;
return flag;
} struct army {
int use,val,bel,nxt;
};
army a[maxn];
int start_a[maxn];
bool cmp(const army a,const army b)
{
if(a.use==b.use)
return a.val<b.val;
return a.use<b.use;
} bool check(int x)
{
int army_tot=0,army_lst,uncow[maxn]={0},uncow_cnt=0;
memset(a,0,sizeof(a));
memset(vis,0,sizeof(vis));
memset(start_a,0,sizeof(start_a));
REP(i,1,m)
{
int u=st[i],now=0;
DREP(j,16,0)if(p[u][j] && now+pw[u][j]<=x)
{
if(j==0)army_lst=u;
now+=pw[u][j];
u=p[u][j];
}
if(u!=1)vis[u]=1;
else
{
army_tot++;
a[army_tot]={0,x-now,army_lst,start_a[army_lst]};
start_a[army_lst]=army_tot;
}
}
uncow_cnt=0;
EREP(i,1)
{
int v=e[i].v,mn=e[i].w,mn_j;
if(dfs1(v,1))continue;
for(int j=start_a[v];j;j=a[j].nxt)
if(a[j].val<mn)
{
mn=a[j].val;
mn_j=j;
}
if(mn<e[i].w)a[mn_j].use=1;
else uncow[++uncow_cnt]=pw[v][0];
}
sort(uncow,uncow+1+uncow_cnt);
sort(a+1,a+army_tot+1,cmp);
int j=1;
REP(i,1,uncow_cnt)
{
while(a[j].val<uncow[i] && !a[j].use && j<=army_tot)j++;
if(j>army_tot || a[j].use)return false;
j++;
}
return true;
} void doing()
{
int l=1,r=Sum;
while(l<r)
{
int mid=(l+r)>>1;
if(check(mid))r=mid;
else l=mid+1;
}
cout<<l<<endl;
} int main()
{
init();
doing();
return 0;
}

【NOIP2012】 疫情控制的更多相关文章

  1. Luogu 1084 NOIP2012 疫情控制 (二分,贪心,倍增)

    Luogu 1084 NOIP2012 疫情控制 (二分,贪心,倍增) Description H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树, 1 号城市是首都, 也是 ...

  2. [NOIP2012]疫情控制 贪心 二分

    题面:[NOIP2012]疫情控制 题解: 大体思路很好想,但是有个细节很难想QAQ 首先要求最大时间最小,这种一般都是二分,于是我们二分一个时间,得到一个log. 然后发现一个军队,越往上走肯定可以 ...

  3. NOIP2012 疫情控制 题解(LuoguP1084)

    NOIP2012 疫情控制 题解(LuoguP1084) 不难发现,如果一个点向上移动一定能控制更多的点,所以可以二分时间,判断是否可行. 但根节点不能不能控制,存在以当前时间可以走到根节点的点,可使 ...

  4. noip2012 疫情控制

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

  5. NOIP2012疫情控制(二分答案+倍增+贪心)

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

  6. [NOIP2012]疫情控制(二分答案+倍增+贪心)

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

  7. [NOIp2012]疫情控制 题解

    好久没更,强迫自己写一篇. 神 tm 大预言家出的题 注意到如果 \(x\) 小时可以控制住疫情,则 \(\forall x'>x\) 必然也可以控制住疫情,显然答案具有单调性,可以二分答案. ...

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

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

  9. noip2012疫情控制 题解

    题目大意 给出一棵n个节点的树,根是1,要在除根节点以外的点建立检查点,使得从每条根到叶子的路径上都至少存在一个检查点.检查点由军队来建立.初始军队的位置是给定的,移动军队走一条边需要花费这条边的权值 ...

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

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

随机推荐

  1. 织梦CMS搭建网站必做的服务器相关安全设置

    http://help.dedecms.com/install-use/server/2011/1109/2124.html#printSource http://www.aliweihu.com/9 ...

  2. ffmpeg批量实现视频转码命令行

    ffmpeg实现视频转码命令行,result需要提前建好作为保存转码后的视频路径: ffmpeg -i .mp4 -vcodec h264 "result\1.mp4" 当有大量视 ...

  3. hibernate.dialect是干嘛用的?

    dialect[ˈdaɪəlekt]就是“方言”,因为hibernate是要把Java对象转换成关系数据库来描述的,而关系数据库虽然有一些统一的标准,如SQL-92等,但是实际上各数据库如Oracle ...

  4. -------- ROOTKIT 核心技术——系统服务调度表挂钩调试(PART III) --------

    ---------------------------------------------------------------------------------------- 本篇开始进行真枪实弹的 ...

  5. winform程序压缩文件上传,服务器端asp.net mvc进行接收解压

    期间编程没什么难度,唯一可能忽略导致结果失败是asp.net  mvc配置 对于压缩文件大的话,需要配置mvc的最大接收量: <system.web> <httpRuntime ma ...

  6. linux 保留内核中sas驱动的加载导致crash问题

    [root@localhost ~]# uname -a Linux localhost.localdomain -.el7.x86_64 问题描述,在crash的时候,小内核因为分配中断号失败而触发 ...

  7. javascript函数之arguments

    function foo(x,y,z){ console.info (arguments.length); //2 实际的参数个数 console.info(arguments[0]); //传入的第 ...

  8. python_如何统计序列中元素

    问题1: 随机数列[12,5,8,7,8,9,4,8,5,...] 中出现次数最高的3个元素,他们出现的次数 问题2: 对某英文文章的单词,进行词频统计,找出出现次数最搞得10个单词,他们出现的次数是 ...

  9. 【bird-java】分布式服务间的事件总线EventBus

    什么是EventBusEventBus是对发布-订阅模式的一种实现.其以一种非常优雅的方式实现了组件间的解耦与通信,在Android开发.DDD等领域都有非常广泛的应用. 事件流大致如下: Produ ...

  10. 转-Windows路由表配置:双网卡路由分流

    原文链接:http://www.cnblogs.com/lightnear/archive/2013/02/03/2890835.html 一.windows 路由表解释 route print -4 ...