NOIP 2012 疫情控制(二分+贪心+倍增)
题解
二分时间
然后一个显然的事是一个军队向上爬的越高它控制的点越多
所以首先军队尽量往上爬。
当一个军队可以爬到根节点我们记录下它的剩余时间T和它到达根结点时经过的根节点的子节点son。
当一个军队爬不到根节点时我们就让它控制它可以爬到的最高点。
然后我们把爬到根节点的军队按T从小到大排序。
然后按顺序处理
然后假如一个军队没有时间回到它的son,且son还没有控制。就让它控制son。
因为让别的军队去控制它显然更浪费时间。
否则贪心地匹配就好了(尽量小的和小的和匹配)
然后向上爬用倍增来优化。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 priority_queue<long long,vector<long long>,greater<long long> > q1,q2; 9 const int N=57010; 10 int cnt,head[N],fa[N][21],s[N][21],top[N],book[N],xb[N],ww[N],www[N],n,m; 11 long long rest[N]; 12 struct edge{ 13 int nxt,to,w; 14 }e[500000]; 15 struct node{ 16 int id,xb; 17 long long rest; 18 }k[N]; 19 bool cmp(node a,node b){ 20 return a.rest<b.rest; 21 } 22 void add(int u,int v,int w){ 23 cnt++; 24 e[cnt].nxt=head[u]; 25 e[cnt].to=v; 26 e[cnt].w=w; 27 head[u]=cnt; 28 } 29 void dfs(int u,int f,int fl){ 30 fa[u][0]=f; 31 s[u][0]=fl; 32 for(int i=1;i<=17;i++){ 33 fa[u][i]=fa[fa[u][i-1]][i-1]; 34 s[u][i]=s[fa[u][i-1]][i-1]+s[u][i-1]; 35 } 36 for(int i=head[u];i;i=e[i].nxt){ 37 int v=e[i].to; 38 if(v==f)continue; 39 dfs(v,u,e[i].w); 40 } 41 } 42 void dfs1(int u,int f,int tp){ 43 top[u]=tp; 44 for(int i=head[u];i;i=e[i].nxt){ 45 int v=e[i].to; 46 if(v==f)continue; 47 dfs1(v,u,tp); 48 } 49 } 50 void dfs2(int u,int f){ 51 if(book[u]==1)return; 52 book[u]=1; 53 bool flag=false; 54 for(int i=head[u];i;i=e[i].nxt){ 55 int v=e[i].to; 56 if(v==f)continue; 57 dfs2(v,u); 58 if(book[v]==0)book[u]=0; 59 flag=true; 60 } 61 if(!flag)book[u]=0; 62 } 63 bool pd(long long maxx){ 64 while(!q1.empty())q1.pop(); 65 while(!q2.empty())q2.pop(); 66 for(int i=1;i<=n;i++)book[i]=0; 67 for(int i=1;i<=m;i++){ 68 k[i].xb=ww[i]; 69 k[i].rest=maxx; 70 k[i].id=i; 71 for(int j=17;j>=0;j--){ 72 if(fa[k[i].xb][j]&&k[i].rest>=s[k[i].xb][j]){ 73 k[i].rest-=s[k[i].xb][j]; 74 k[i].xb=fa[k[i].xb][j]; 75 } 76 } 77 } 78 sort(k+1,k+1+m,cmp); 79 for(int i=1;i<=m;i++){ 80 if(k[i].xb!=1)book[k[i].xb]=1; 81 } 82 dfs2(1,0); 83 for(int i=1;i<=m;i++){ 84 if(k[i].xb==1&&k[i].rest<www[top[ww[k[i].id]]]&&book[top[ww[k[i].id]]]==0)book[top[ww[k[i].id]]]=1; 85 else if(k[i].xb==1&&(k[i].rest>=www[top[ww[k[i].id]]]||(k[i].rest<www[top[ww[k[i].id]]]&&book[top[ww[k[i].id]]])))q1.push(k[i].rest); 86 } 87 if(book[1])return true; 88 for(int i=head[1];i;i=e[i].nxt){ 89 if(book[e[i].to]==0)q2.push(e[i].w); 90 } 91 while(!q2.empty()){ 92 int a=q2.top(); 93 q2.pop(); 94 while(!q1.empty()&&q1.top()<a)q1.pop(); 95 if(q1.empty())return false; 96 q1.pop(); 97 } 98 return true; 99 } 100 int main(){ 101 scanf("%d",&n); 102 for(int i=1,u,v,w;i<=n-1;i++){ 103 scanf("%d%d%d",&u,&v,&w); 104 add(u,v,w); 105 add(v,u,w); 106 } 107 for(int i=head[1];i;i=e[i].nxt){ 108 www[e[i].to]=e[i].w; 109 dfs1(e[i].to,1,e[i].to); 110 } 111 dfs(1,0,0); 112 scanf("%d",&m); 113 for(int i=1;i<=m;i++){ 114 scanf("%d",&ww[i]); 115 } 116 long long l=0,r=50000000000009,ans; 117 while(l<=r){ 118 long long mid=(l+r)>>1; 119 if(pd(mid)){ 120 r=mid-1; 121 ans=mid; 122 } 123 else l=mid+1; 124 } 125 if(r==50000000000009)printf("-1"); 126 else printf("%lld",ans); 127 return 0; 128 }