zoukankan      html  css  js  c++  java
  • 疫情控制

    洛谷

    其实在很久之前我就差不多大致理解思路

    但由于过于蒟蒻

    难以实现

    在大约一月前我刷树形dp时,又刷到这道题

    嗯,我用dp get到0pts的好成绩

    反正我现在就是懂了

    #include<bits/stdc++.h>
    #define re return
    #define ll long long
    #define dec(i,l,r) for(register int i=l;i>=r;--i)
    #define inc(i,l,r) for(register int i=l;i<=r;++i) 
    using namespace std;
    template<typename T>inline void rd(T&x)
    {
        char c;bool f=0;
        while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
        x=c^48;
        while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
        if(f)x=-x;
    }
    
    const int maxn=300005;
    int cnt,k,n,m,hd[maxn],fa[maxn][21];
    int size1,pos[maxn],vis[maxn];
    
    long long dis[maxn][21];
    
    struct node{
        int to,nt,val;
    }e[maxn<<1];
    inline void add(int x,int y,int z)
    {
        e[++k].to=y;e[k].nt=hd[x];hd[x]=k;e[k].val=z;
        e[++k].to=x;e[k].nt=hd[y];hd[y]=k;e[k].val=z;
    }
    
    
    inline void dfs(int x)
    {
        for(int i=0;fa[fa[x][i]][i];++i)
        {
            fa[x][i+1]=fa[fa[x][i]][i];
            dis[x][i+1]=dis[x][i]+dis[fa[x][i]][i];
        }
        
        for(int i=hd[x];i;i=e[i].nt)
        {
            int v=e[i].to;
            if(v==fa[x][0])continue;
            fa[v][0]=x;
            dis[v][0]=e[i].val;
            dfs(v);
        }
    }
    
    struct lll
    {
        int fr,left_dis,id;
        bool operator<(lll c)const
        {
            re left_dis<c.left_dis;
        }
    }a[maxn];
    
    int cnta,cntb,need[maxn];
    struct lli
    {
        int val,id;
        bool operator<(lli c)const
        {
            re val<c.val;
        }
    }b[maxn];
    
    inline bool dfs1(int x)
    {
        if(vis[x])re 1;
        int siz=0;
        for(int i=hd[x];i;i=e[i].nt)
        {
            int v=e[i].to;
            if(v==fa[x][0])continue;
            siz|=1;
            if(dfs1(v)==0)
            {vis[x]=0;re 0;}
        }
        if(!siz)
            {vis[x]=0;re 0;}
        vis[x]=1;
        re 1;
    }
    
    inline bool check(ll x)
    {
        cntb=cnta=0;
        inc(i,0,n)vis[i]=0; 
        
        inc(i,1,m)
        {
            int v=pos[i],now=0;
            dec(i,20,0)if(fa[v][i]>1&&dis[v][i]+now<=x){now+=dis[v][i];v=fa[v][i];}
            
            int left=x-now-dis[v][0];
            
            if(fa[v][0]==1&&left>=0)
            //在边界点//能返回点或者已被注扎 
            //left是从1出发能走的最远距离 
                a[++cnta]=(lll){v,left,cnta};
            
            else vis[v]=1;
        }
        
        //将不能被封闭的点标记 
        for(int i=hd[1];i;i=e[i].nt)
        {
            int v=e[i].to;
            dfs1(v);
        }
        
        sort(a+1,a+cnta+1);
        int nowa=0;
        
        
        //找到最小的不能返回出发节点(未封闭)的值 
        inc(i,1,cnta)
        {
            if(!vis[a[i].fr]&&a[i].left_dis<dis[a[i].fr][0])
            {
                a[i].left_dis=-1;
                vis[a[i].fr]=1;
                --nowa;
            }
        }
        
        sort(a+1,a+cnta+1);
        for(int i=hd[1];i;i=e[i].nt)
        {
            int v=e[i].to;
            if(!vis[v])b[++cntb]=(lli){e[i].val,v};
        }
        sort(b+1,b+cntb+1);
        
        int nowb=1;
        inc(i,nowa+1,cnta)
        {
            if(b[nowb].val<=a[i].left_dis)++nowb;
            if(nowb==cntb+1)re 1;
        }
        
        re 0;
    }
    int main()
    {
    freopen("in.txt","r",stdin);
    //    freopen("testdata.in","r",stdin);
        int x,y,z;    
        ll l=0,r=0;
        rd(n);
        inc(i,2,n)
        {
            rd(x),rd(y),rd(z);
            add(x,y,z);
            r+=z;
        }
        
        //dfs得到倍增数组 
        for(int i=hd[1];i;i=e[i].nt)
        {
            ++size1;
            int v=e[i].to;
            fa[v][0]=1;dis[v][0]=e[i].val;
            dfs(v);
        }    
        
        rd(m);
        if(m<size1){printf("-1");re 0;}
        
        inc(i,1,m)rd(pos[i]);
    
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(check(mid))r=mid-1;
            else l=mid+1;
        }
        
        printf("%lld",l);
        re 0;
    } 
  • 相关阅读:
    Docker之Harbor
    idea 代码块编辑(批量列编辑)快捷键 -- idea version 2018 不常用
    mysql 去除表中重复的数据,保留id最小的数据信息
    打家劫舍(动态规划+滚动数组+取模运算优化)
    利用线程异步调用
    idea 2019激活码
    mysql导出PDM表结构并带有注释
    安装GO
    GO语言
    项目启动
  • 原文地址:https://www.cnblogs.com/lsyyy/p/11529933.html
Copyright © 2011-2022 走看看