zoukankan      html  css  js  c++  java
  • [bzoj3677][Apio2014]连珠线【树形dp】

    【题目链接】
      https://www.lydsy.com/JudgeOnline/problem.php?id=3677
    【题解】
      首先一定存在一个点,当他作为根时所有个蓝线都以x-dad[x]-dad[dad[x]]存在。因此可以先确定一个根,O(N)dp一下,然后O(1)换根。
      时间复杂度:O(N)
      

    /* --------------
        user Vanisher
        problem bzoj-3677 
    ----------------*/
    # include <bits/stdc++.h>
    # define    ll      long long
    # define    inf     0x3f3f3f3f
    # define    N       200010
    using namespace std;
    int read(){
        int tmp=0, fh=1; char ch=getchar();
        while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
        while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
        return tmp*fh;
    }
    struct edge{
        int data,next,vote;
    }e[N*2];
    int place,f[N][3],g[N][3],head[N],st[N*2],top,rd[N*2],n,ans,use[N];
    void build(int u, int v, int w){
        e[++place].data=v; e[place].next=head[u]; head[u]=place; e[place].vote=w;
        e[++place].data=u; e[place].next=head[v]; head[v]=place; e[place].vote=w;
    }
    void dp(int x, int fa){
        f[x][0]=0; f[x][1]=-inf; f[x][2]=-inf; 
        for (int ed=head[x]; ed!=0; ed=e[ed].next)
            if (e[ed].data!=fa){
                dp(e[ed].data,x);
                int now=max(f[e[ed].data][1]+e[ed].vote,f[e[ed].data][0]);
                f[x][1]+=now, f[x][2]+=now;
                if (f[x][0]+f[e[ed].data][0]+e[ed].vote>f[x][1]){
                    g[x][2]=g[x][1], f[x][2]=f[x][1];
                    f[x][1]=f[x][0]+f[e[ed].data][0]+e[ed].vote;
                    g[x][1]=e[ed].data;
                }
                else if (f[x][0]+f[e[ed].data][0]+e[ed].vote>f[x][2]){
                    f[x][2]=f[x][0]+f[e[ed].data][0]+e[ed].vote;
                    g[x][2]=e[ed].data;
                }
                f[x][0]=f[x][0]+now;
            }   
    }
    void dfs(int x, int fa){
        st[++top]=x;
        for (int ed=head[x]; ed!=0; ed=e[ed].next)
            if (e[ed].data!=fa){
                rd[top]=e[ed].vote;
                dfs(e[ed].data,x);
                rd[top]=e[ed].vote;
                st[++top]=x;
            }
    }
    int main(){
        n=read();
        for (int i=1; i<n; i++){
            int u=read(), v=read(), w=read();
            build(u,v,w);
        }
        dp(1,0);
        dfs(1,0);
        ans=f[1][0]; use[1]=true;
        for (int i=1; i<top; i++){
            int x=st[i], y=st[i+1], tag;
            if (g[y][1]==x) tag=2; else tag=1;
            f[x][0]=f[x][0]-max(f[y][tag]+rd[i],f[y][0]);
            f[x][1]=f[x][1]-max(f[y][tag]+rd[i],f[y][0]);
            f[x][2]=f[x][2]-max(f[y][tag]+rd[i],f[y][0]);
            if (g[x][1]==y) tag=2; else tag=1;
            if (use[y]==0){
                f[y][1]=f[y][1]+max(f[x][tag]+rd[i],f[x][0]);
                f[y][2]=f[y][2]+max(f[x][tag]+rd[i],f[x][0]);
                if (f[y][0]+f[x][0]+rd[i]>f[y][1]){
                    g[y][2]=g[y][1], f[y][2]=f[y][1];
                    f[y][1]=f[y][0]+f[x][0]+rd[i];
                    g[y][1]=x;
                }
                else if (f[y][0]+f[x][0]+rd[i]>f[y][2]){
                    f[y][2]=f[y][0]+f[x][0]+rd[i];
                    g[y][2]=x;
                }
                use[y]=true;
            }
            else {
                f[y][1]=f[y][1]+max(f[x][tag]+rd[i],f[x][0]);
                f[y][2]=f[y][2]+max(f[x][tag]+rd[i],f[x][0]);
            }
            f[y][0]=f[y][0]+max(f[x][tag]+rd[i],f[x][0]);
            ans=max(ans,f[y][0]);
        }
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    ncover
    bash
    .net framework 工具
    keePass
    jersey
    i-jetty
    如何查看set环境变量的更改
    C语言丨如果你不是程序员,绝对看不懂这三个符号!(= 和==、!=)
    忘记 root 密码怎么办?教你4种使用MySQL方式修改密码!(超实用)
    一线城市容不下肉体,二三线城市安放不了灵魂,程序员何处为家?
  • 原文地址:https://www.cnblogs.com/Vanisher/p/9135966.html
Copyright © 2011-2022 走看看