【NOIP 2012 疫情控制】***

题目描述

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

也是树中的根节点。

H 国的首都爆发了一种危害性极高的传染病。当局为了控制疫情,不让疫情扩散到边境

城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从首都到边境

城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点。但特别要注意的是,

首都是不能建立检查点的。

现在,在 H 国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队。一支军队可以在有道路连接的城市间移动,并在除首都以外的任意一个城市建立检查点,且只能在

一个城市建立检查点。一支军队经过一条道路从一个城市移动到另一个城市所需要的时间等

于道路的长度(单位:小时)。

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

输入输出格式

输入格式:

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

接下来的 n-1 行,每行 3 个整数,u、v、w,每两个整数之间用一个空格隔开,表示从

城市 u 到城市 v 有一条长为 w 的道路。数据保证输入的是一棵树,且根节点编号为 1。

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

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

的城市的编号。

输出格式:

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

输入输出样例

输入样例#1:
4 
1 2 1 
1 3 2 
3 4 3 
2 
2 2
输出样例#1:
3

说明

【输入输出样例说明】

第一支军队在 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。

NOIP 2012 提高组 第二天 第三题

 

 

又理解错题了,是同时的。

往往不容易直接进行最优解的时候都要考虑一下二分。那么就给你一个限定时间,你在限定时间之内完成就好了。

我们会发现,其实你越往上走,覆盖的路径越多,所以每个点都尽量往上走。

有些点走到了根,有些点没有,没有走到根的点就直接对子树做贡献。走到根的点要合理分配,使得在限定时间内覆盖子树。

这时如果子树没有被覆盖,那么从根往下走一步就好了。

很容易想到贪心,两个都排序,大的对大的,小的对小的。

但是有一个问题,有时候你从子树走到根,然后走不回来了。【但其实他留在那棵子树上可能更好【相当于他下来完全不用时间的

考虑一个子树,从他出发的点剩余时间最少的是x,如果x不能走回来,那么就让x留在那子树上,否则这种情况不用管【因为都能走回来了,就不用管了

为什么走不会来,就直接留下呢,因为这样你覆盖这棵子树一定用了其他点,说明这个点比x更强,那么如果x能做到的事,这个点更能做到,所以x不需做别的,管好这棵子树就好。

 

【倍增打错了,捂脸

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<queue>
  7 #include<cmath>
  8 using namespace std;
  9 #define Maxn 50010
 10 #define Maxd 25
 11 #define INF 0xfffffff
 12 #define LL long long
 13 
 14 struct node
 15 {
 16     LL x,y,next,c;
 17 }t[Maxn*2];LL len;
 18 LL first[Maxn];
 19 LL n,m;
 20 
 21 void ins(LL x,LL y,LL c)
 22 {
 23     t[++len].x=x;t[len].y=y;t[len].c=c;
 24     t[len].next=first[x];first[x]=len;
 25 }
 26 
 27 LL mymin(LL x,LL y) {return x<y?x:y;}
 28 
 29 bool am[Maxn];
 30 LL ff[Maxn],d[Maxn][Maxd],f[Maxn][Maxd],id[Maxn];
 31 LL dis[Maxn],dep[Maxn];
 32 
 33 void dfs(LL x,LL fa)
 34 {
 35     for(LL i=1;i<=18;i++)
 36         d[x][i]=d[f[x][i-1]][i-1],f[x][i]=f[f[x][i-1]][i-1];
 37     if(fa==1) ff[x]=x;
 38     else ff[x]=ff[fa];
 39     for(LL i=first[x];i;i=t[i].next) if(t[i].y!=fa)
 40     {
 41         LL y=t[i].y;
 42         d[y][0]=t[i].c;f[y][0]=x;
 43         dis[y]=dis[x]+t[i].c;dep[y]=dep[x]+1;
 44         dfs(y,x);
 45     }
 46 }
 47 
 48 LL mn[Maxn];
 49 bool g[Maxn];
 50 void dfs2(LL x,LL fa)
 51 {
 52     LL ans=0;
 53     bool ok=1,sm=0;
 54     for(LL i=first[x];i;i=t[i].next) if(t[i].y!=fa)
 55     {
 56         sm=1;
 57         LL y=t[i].y;
 58         dfs2(y,x);
 59         if(!g[y]) ok=0;
 60     }
 61     if(am[x]||(ok&&sm)) g[x]=1;
 62 }
 63 
 64 struct hp
 65 {
 66     LL x,w;
 67 }q1[Maxn],q2[Maxn];
 68 
 69 LL lf[Maxn];
 70 
 71 bool cmp(hp x,hp y) {return x.w<y.w;}
 72 
 73 bool us[Maxn];
 74 bool check(LL x)
 75 {
 76     memset(am,0,sizeof(am));
 77     memset(g,0,sizeof(g));
 78     memset(lf,-1,sizeof(lf));
 79     for(LL i=first[1];i;i=t[i].next) mn[t[i].y]=-1;
 80     LL xx;
 81     for(LL i=1;i<=m;i++)
 82     {
 83         LL now=id[i];xx=x;
 84         for(LL j=18;j>=0;j--)
 85         {
 86             if((1<<j)<=dep[now]&&dis[now]-dis[f[now][j]]<=xx)
 87             {
 88                 xx-=dis[now]-dis[f[now][j]];
 89                 now=f[now][j];
 90             }
 91         }
 92         am[now]=1;
 93         if(now==1) lf[i]=x-dis[id[i]];
 94         if(now==1&&(mn[ff[id[i]]]==-1||lf[mn[ff[id[i]]]]>lf[i])) mn[ff[id[i]]]=i;
 95     }
 96     dfs2(1,0);
 97     LL l1=0,l2=0;
 98     for(LL i=1;i<=m;i++) if(lf[i]!=-1) q1[++l1].x=i,q1[l1].w=lf[i];
 99     // for(LL i=1;i<=m;i++) if(id[i]==1) q1[++l1].x=0,q1[l1].w=x;
100     for(LL i=first[1];i;i=t[i].next)
101     {
102         LL y=t[i].y;
103         if(!g[y]) q2[++l2].x=y,q2[l2].w=t[i].c;
104     }
105     memset(g,0,sizeof(g));
106     sort(q1+1,q1+1+l1,cmp);
107     sort(q2+1,q2+1+l2,cmp);
108     LL j=1,i;
109     // LL k=l1;
110     if(l1<l2) return 0;
111     for(i=1;i<=l2;i++)if(mn[q2[i].x]!=-1&&g[mn[q2[i].x]]==0&&lf[mn[q2[i].x]]<q2[i].w) 
112         {
113             g[mn[q2[i].x]]=1;
114             q2[i].x=-1;
115         }
116         
117     for(i=1;i<=l2;i++) if(q2[i].x!=-1)
118     {
119         while(g[q1[j].x]&&j<=l1) j++;
120         // if(j>l1) return 0;
121         /*if(mn[q2[i].x]!=-1&&g[mn[q2[i].x]]==0&&lf[mn[q2[i].x]]<q2[i].w) 
122         {
123             g[mn[q2[i].x]]=1;
124             continue;
125         }*/
126         /*else*/ if(mn[q2[i].x]==-1||lf[mn[q2[i].x]]>=q2[i].w)
127         {
128             while((g[q1[j].x]||q1[j].w<q2[i].w)&&j<=l1) j++;
129         }
130         if(j>l1) return 0;
131         g[q1[j].x]=1;
132         j++;
133     }
134     return 1;
135 }
136 
137 void ffind(LL l,LL r)
138 {
139     LL ans=-1;
140     while(l<r)
141     {
142         LL mid=(l+r)>>1;
143         if(check(mid)) ans=mid,r=mid;
144         else l=mid+1;
145     }
146     if(check(l)) ans=l;
147     printf("%lld\n",ans);
148 }
149 
150 int main()
151 {
152     scanf("%lld",&n);
153     len=0;
154     memset(first,0,sizeof(first));
155     LL sum=0;
156     for(LL i=1;i<n;i++)
157     {
158         LL x,y,c;
159         scanf("%lld%lld%lld",&x,&y,&c);
160         ins(x,y,c);ins(y,x,c);
161         sum+=c;
162     }
163     memset(am,0,sizeof(am));
164     scanf("%lld",&m);
165     for(LL i=1;i<=m;i++)
166     {
167         LL x;
168         scanf("%lld",&x);
169         am[x]++;
170         id[i]=x;
171     }
172     f[1][0]=0;
173     dis[0]=0;dep[0]=0;
174     dfs(1,0);
175     ffind(0,sum);
176     return 0;
177 }
View Code

 

【打得丑并且调了一个晚上,捂脸= =

 

2016-11-17 07:52:50

posted @ 2016-11-17 07:48  konjak魔芋  阅读(771)  评论(1编辑  收藏  举报