• BZOJ 3677: [Apio2014]连珠线 树形DP


    倒在了性质分析上....(还有仔细读题)

    仔细读题后,我们发现红色边只能连接一个连通块和一个叶节点(或两个叶节点).

    然后如果一个状态是合法的,当且仅当以某个点为根时所有蓝边都是形如 son[x]->x->fa[x]

    然后因为有这条性质,我们就可以进行树形DP了.

    令 $1$ 为根,$f[x]$ 表示 $x$ 是蓝边中点时以 $x$ 为根的子树的最大价值,$g[x]$ 表示不是中点时的最大价值.

    然后当根不是 $1$ 时,用换根DP的方式转移即可,需要记录一个最小/次小值跟着一起转移.

    #include <cstdio>  
    #include <string>
    #include <cstring>
    #include <algorithm>  
    #define N 200007 
    #define inf 1000000000 
    using namespace std;    
    void setIO(string s) 
    {
        string in=s+".in"; 
        string out=s+".out"; 
        freopen(in.c_str(),"r",stdin); 
        // freopen(out.c_str(),"w",stdout); 
    } 
    int edges,n,ans;  
    int f[N],g[N],hd[N],to[N<<1],nex[N<<1],val[N<<1],f1[N],f2[N];      
    void add(int u,int v,int c) 
    {
        nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c; 
    }
    void dfs(int u,int ff) 
    {   
        g[u]=0,f[u]=-inf;  
        f1[u]=f2[u]=-inf;  
        for(int i=hd[u];i;i=nex[i]) 
        {
            int v=to[i]; 
            if(v==ff) continue;   
            dfs(v,u); 
            g[u]+=max(g[v],f[v]+val[i]);                    
        }    
        for(int i=hd[u];i;i=nex[i]) 
        {
            int v=to[i]; 
            if(v==ff) continue;         
            f[u]=max(f[u],g[u]-max(g[v],f[v]+val[i])+g[v]+val[i]);   
            int tmp=g[v]+val[i]-max(g[v],f[v]+val[i]);    
            if(tmp>f1[u]) f2[u]=f1[u],f1[u]=tmp;        
            else if(tmp>f2[u]) f2[u]=tmp;      
        }
    }
    void dfs2(int u,int ff) 
    {  
        ans=max(ans,g[u]);   
        for(int i=hd[u];i;i=nex[i]) 
        {
            int v=to[i];   
            if(v==ff) continue;     
            int gu=g[u]-max(g[v],g[v]+f1[v]+val[i]),fu;    
            if(f1[u]==g[v]+val[i]-max(g[v],g[v]+f1[v]+val[i])) fu=f2[u];     
            else fu=f1[u];   
            g[v]+=max(gu,gu+fu+val[i]);       
            fu=gu+val[i]-max(gu,gu+fu+val[i]);      
            if(fu>f1[v]) f2[v]=f1[v],f1[v]=fu;   
            else if(fu>f2[v]) f2[v]=fu; 
            dfs2(v,u);   
        }
    }
    int main() 
    { 
        // setIO("input");  
        int i,j,x,y,z; 
        scanf("%d",&n);  
        for(i=1;i<n;++i) scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,z);   
        ans=-inf; 
        dfs(1,0);   
        dfs2(1,0); 
        printf("%d
    ",ans); 
        return 0; 
    }
    

      

  • 相关阅读:
    工作10年写不好一封邮件?
    邮件狂人告诉你:如何打造最强邮件处理流
    免费瘫软入院,付费发飙成壮汉,YoMail 想干嘛?
    我们要招5-10人,全要技术!
    如何有效的报告bug?
    黑科技 | 用实力打造邮件沟通新模式
    李叫兽去了百度,我们来聊聊营销
    你好,我想送你一本书
    上了这套密码锁,你就无敌了
    YoMail 邮箱客户端的社会化之路,起于邮箱,不止于邮件
  • 原文地址:https://www.cnblogs.com/guangheli/p/12131872.html
Copyright © 2020-2023  润新知