[NOIP2012]疫情控制

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

思路{

  此题初看毫无头绪。但是非常直观。

  然而我们可以直观地看到,每个点应该尽量往上走或不动。

  由于答案是具有单调性的,我们可以二分+倍增。

  可以得出走完后还可走多少路程和点的状态:记录还可接着走的,标记已经走完了的。

  处理还有多少根的子节点没有走完,用走完了的点去怼它。

  由于考虑最优,大怼小划不来,小怼小,大怼大,所以从小到大sort。

}

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<vector>
 6 #include<queue>
 7 #include<ctime>
 8 #include<cmath>
 9 #include<list>
10 #include<deque>
11 #include<stack>
12 #include<map>
13 #include<set>
14 #define RG register
15 #define LL long long
16 #define dd double
17 #define maxx 50001
18 #define V e[i].to
19 using namespace std;
20 struct ee{int nxt,to,c;}e[maxx*2];
21 struct matrix{
22   int u,s;
23   matrix() {}
24   matrix(int U,int S):u(U),s(S) {}
25 }ha[maxx];
26 int head[maxx],f[maxx][21],g[maxx][21],n,m,pos[maxx],w[maxx],b[maxx],tot;bool tag[maxx];
27 bool comp1(const matrix & a,const matrix & b){return a.s<b.s;}
28 bool comp2(const int a,const int b){return e[a].c<e[b].c;}
29 void add(int u,int v,int c){e[tot].nxt=head[u],e[tot].to=v;e[tot].c=c;head[u]=tot++;}
30 void dfs(int u,int fa){g[u][0]=fa,b[u]=b[fa];for(RG int i=head[u];i!=-1;i=e[i].nxt)if(V!=fa)f[V][0]=e[i].c,dfs(V,u);}
31 bool vis(int u,int fa){if(tag[u])return 1;bool flag=false;
32   for(int i=head[u];i!=-1;i=e[i].nxt)if(V!=fa){flag=1;if(!vis(V,u))return 0;}return flag;
33 }
34 bool check(LL upp){memset(tag,false,sizeof(tag));ha[0].s=w[0]=0;
35   for(RG int i=1;i<=m;++i){
36     int p=pos[i];LL dis=0;
37     for(RG int k=20;k!=-1&&p!=1;k--)if(f[p][k]<=upp-dis)dis+=f[p][k],p=g[p][k];
38     if(p==1)ha[++ha[0].s]=matrix(pos[i],upp-dis);
39     else tag[p]=true;
40   }for(RG int i=head[1];i!=-1;i=e[i].nxt)if(!vis(V,1))w[++w[0]]=i;else tag[V]=true;
41   if(w[0]>ha[0].s)return false;sort(ha+1,ha+ha[0].s+1,comp1);sort(w+1,w+w[0]+1,comp2);int j=1;
42   for(RG int i=1;i<=ha[0].s;++i){
43     if(!tag[b[ha[i].u]])tag[b[ha[i].u]]=true;// an ju le ye
44     else {for(;j<=w[0]&&tag[e[w[j]].to];++j);if(j<=w[0]&&ha[i].s>=e[w[j]].c)tag[e[w[j++]].to]=1;}
45     for(;j<=w[0]&&tag[e[w[j]].to];++j);if(j>w[0])return true;
46   }return false;
47 }
48 int main(){
49   LL L=0,ans=0,R=0;int x,y,z;memset(head,-1,sizeof(head));
50   scanf("%d",&n);for(RG int i=1;i<n;++i)scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,z),R+=z;
51   scanf("%d",&m);for(RG int i=1;i<=m;++i)scanf("%d",&pos[i]);
52   for(RG int i=0;i<=20;++i)g[1][i]=1;for(int i=head[1];i!=-1;i=e[i].nxt)b[1]=V,f[V][0]=e[i].c,dfs(V,1);b[1]=0;
53   for(RG int j=1;j<=20;++j)for(RG int i=1;i<=n;++i)g[i][j]=g[g[i][j-1]][j-1],f[i][j]=f[i][j-1]+f[g[i][j-1]][j-1];
54   while(L<=R){LL mid=(L+R)>>1;if(check(mid))R=mid-1,ans=mid;else L=mid+1;}printf("%lld",ans);
55   return 0;
56 }

 


posted @ 2017-05-20 11:04  QYP_2002  阅读(217)  评论(0编辑  收藏  举报