• luogu1084 [NOIp2012]疫情控制 (二分答案+倍增+dfs序)


    先二分出一个时间,把每个军队倍增往上跳到不能再跳

    然后如果它能到1号点,就记下来它跳到1号点后剩余的时间;如果不能,就让它就地扎根,记一记它覆盖了哪些叶节点(我在这里用了dfs序+差分,其实直接dfs就行..)

    然后对于那些叶节点没有被覆盖完全的(父亲为1号点的)子树,肯定需要一些已经到1号点的军队来走过去

    如果它离1距离越远,肯定就希望用剩余时间越多的军队来走,除非是有一个剩余时间更少的军队本来就在这个子树里

    看一看能不能符合要求的就行了

    然而有很多要注意的地方:

    0.一个军队只能用一次......(开始读错题 还在想为什么会有-1的情况)

    1.只需要覆盖叶节点就行了,也就是说,统计这个子树有没有完全被覆盖的时候,不能统计到非叶节点

    2.即使有军队本来在这个子树里,我也有可能不选这个军队来到这个子树里,因为它的剩余时间可能非常大

    3.有可能到1号点的军队数不足覆盖掉那些没被覆盖的子树,这时候也是-1

    4.每次judge要清零...

      1 #include<bits/stdc++.h>
      2 #define pa pair<int,int>
      3 #define CLR(a,x) memset(a,x,sizeof(a))
      4 using namespace std;
      5 typedef long long ll;
      6 const int maxn=5e4+10;
      7 
      8 inline ll rd(){
      9     ll x=0;char c=getchar();int neg=1;
     10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
     11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
     12     return x*neg;
     13 }
     14 
     15 struct Edge{
     16     int b,ne;ll l;
     17 }eg[maxn*2];
     18 int egh[maxn],ect;
     19 int N,M,p[maxn];
     20 int dfn[maxn][2],tot,fa[maxn][20];
     21 int bel[maxn],cnt[maxn],tmp[maxn],tmp2[maxn];
     22 int mim[maxn],id[maxn];
     23 bool flag[maxn],islef[maxn];
     24 ll dis[maxn][20],rest[maxn];
     25 
     26 inline void adeg(int a,int b,ll l){
     27     eg[++ect].b=b;eg[ect].l=l;eg[ect].ne=egh[a];egh[a]=ect;
     28 }
     29 
     30 void dfs(int x){
     31     dfn[x][0]=++tot;id[tot]=x;
     32     for(int i=0;fa[x][i]&&fa[fa[x][i]][i];i++){
     33         fa[x][i+1]=fa[fa[x][i]][i];
     34         dis[x][i+1]=dis[x][i]+dis[fa[x][i]][i];
     35     }islef[x]=1;
     36     for(int i=egh[x];i;i=eg[i].ne){
     37         int b=eg[i].b;
     38         if(b==fa[x][0]) continue;
     39         fa[b][0]=x;dis[b][0]=eg[i].l;
     40         if(x==1) bel[b]=b;
     41         else bel[b]=bel[x];
     42         dfs(b);
     43         islef[x]=0;
     44     }
     45     dfn[x][1]=tot;
     46 }
     47 
     48 int getfe(int x,ll &lim){
     49     for(int i=17;i>=0;i--){
     50         if(fa[x][i]&&dis[x][i]<=lim) lim-=dis[x][i],x=fa[x][i];
     51     }
     52     return x;
     53 }
     54 
     55 inline bool cmp(int a,int b){return rest[a]>rest[b];}
     56 inline bool cmp2(int a,int b){return dis[a][0]>dis[b][0];}
     57 
     58 inline bool judge(ll m){
     59     // printf("!!%lld:
    ",m);
     60     int n,i,j;
     61     CLR(cnt,0);
     62     for(i=1,j=0;i<=M;i++){
     63         rest[i]=m;
     64         int x=getfe(p[i],rest[i]);
     65         // printf("%d %d %lld
    ",p[i],x,rest[i]);
     66         if(x==1) tmp[++j]=i;
     67         else{
     68             cnt[dfn[x][0]]++;
     69             cnt[dfn[x][1]+1]--;
     70         }
     71     }
     72     n=j;sort(tmp+1,tmp+n+1,cmp);
     73     CLR(flag,1);
     74     for(i=2,j=0;i<=N;i++){
     75         j+=cnt[i];
     76         if(j==0&&islef[id[i]]) flag[bel[id[i]]]=0;
     77     }
     78     CLR(mim,0);
     79     for(i=n;i;i--){
     80         if((!flag[bel[p[tmp[i]]]])&&(!mim[bel[p[tmp[i]]]])){
     81             mim[bel[p[tmp[i]]]]=i;
     82         }
     83     }
     84     for(i=2,j=0;i<=N;i++){
     85         if(fa[i][0]!=1||flag[i]) continue;
     86         tmp2[++j]=i;
     87     }m=j;
     88     sort(tmp2+1,tmp2+m+1,cmp2);
     89     if(n<m) return 0;
     90     for(i=1,j=1;i<=n&&j<=m;i++){
     91         if(!tmp[i]) continue;
     92         if(tmp[mim[tmp2[j]]]){
     93             tmp[mim[tmp2[j]]]=0;
     94             i--;
     95         }else{
     96             if(rest[tmp[i]]<dis[tmp2[j]][0]) return 0;
     97             tmp[i]=0;
     98         }j++;
     99     }
    100     return j>m;
    101 }
    102 
    103 int main(){
    104     // freopen("testdata (1).in","r",stdin);
    105     int i,j,k;
    106     N=rd();
    107     for(i=1;i<N;i++){
    108         int a=rd(),b=rd(),c=rd();
    109         adeg(a,b,c);adeg(b,a,c);
    110     }dfs(1);
    111     M=rd();
    112     for(i=1;i<=M;i++) p[i]=rd();
    113     ll l=0,r=1e15,ans=1e15+1;
    114     while(l<=r){
    115         ll m=l+r>>1;
    116         if(judge(m)) ans=m,r=m-1;
    117         else l=m+1;
    118     }
    119     if(ans==1e15+1) printf("-1
    ");
    120     else printf("%lld
    ",ans);
    121     return 0;
    122 }
  • 相关阅读:
    CF44G Shooting Gallery KDtree
    UVA12297 Super Poker 矩阵快速幂
    一些刷题的OJ
    关于博客园里的代码那些事
    Linux高并发网络编程开发——epoll-udp
    Linux高并发网络编程开发——tcp状态转换-select-poll
    Linux高并发网络编程开发——tcp三次握手-并发
    Linux高并发网络编程开发——网络编程基础-socket
    Linux系统编程——线程同步
    Linux系统编程——守护进程+线程
  • 原文地址:https://www.cnblogs.com/Ressed/p/9735581.html
Copyright © 2020-2023  润新知