zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    推销
    5132. 颜色交替的最短路径
    5130. 等价多米诺骨牌对的数量
    @babel/plugin-transform-runtime和@babel/preset-env的区别
    5128. 最深叶节点的最近公共祖先(二叉树)
    1094. 拼车
    1109. 航班预订统计(数组)
    5129. 表现良好的最长时间段(数组)
    path.resove 和 path.join
    【原生】 call、apply、bind 的基本使用方法,已经解析了某些源码
  • 原文地址:https://www.cnblogs.com/Xu-daxia/p/9416258.html
Copyright © 2011-2022 走看看