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 }
View Code
原文地址:https://www.cnblogs.com/Xu-daxia/p/9416258.html