zoukankan      html  css  js  c++  java
  • HDU 5834 Magic boy Bi Luo with his excited tree

    树形dp。

    先dfs一次处理子树上的最优解,记录一下回到这个点和不回到这个点的最优解。

    然后从上到下可以推出所有答案。细节较多,很容易写错。

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    #include<iostream>
    #include<ctime>
    using namespace std;
    typedef long long LL;
    const double pi=acos(-1.0);
    void File()
    {
        freopen("D:\in.txt","r",stdin);
        freopen("D:\out.txt","w",stdout);
    }
    
    const int maxn=100010;
    vector<int>G[maxn],t[2][maxn][2];
    int T,n,v[maxn],dp[maxn][2],ans[maxn],sz;
    struct Edge{int u,v,w;}e[2*maxn];
    bool flag[maxn];
    
    void add(int a,int b,int c)
    {
        e[sz].u=a; e[sz].v=b; e[sz].w=c;
        G[a].push_back(sz++);
    }
    
    void dfs(int x,int f)
    {
        flag[x]=1; dp[x][0]=dp[x][1]=v[x];
    
        int i; if(f==0) i=0; else i=G[x].size()-1;
        while(1)
        {
            if(f==0&&i==G[x].size()) break; if(f==1&&i==-1) break;
    
            int id=G[x][i],to=e[id].v;
            if(flag[to])
            {
                t[f][x][0].push_back(dp[x][0]); t[f][x][1].push_back(dp[x][1]);
                if(f==0) i++; else i--; continue;
            }
    
            dfs(to,f);
    
            int t1=dp[x][1], t2=dp[x][0]+dp[to][1]-e[id].w, t3=dp[x][1]+dp[to][0]-2*e[id].w;
            dp[x][1]=max(t1,max(t2,t3));
            dp[x][0]=dp[x][0]+max(dp[to][0]-2*e[id].w,0);
    
            t[f][x][0].push_back(dp[x][0]); t[f][x][1].push_back(dp[x][1]);
            if(f==0) i++; else i--;
        }
    
    }
    
    void get(int x,int a,int b,int c)
    {
        flag[x]=1;
    
        int t1=dp[x][1];
        int t2=dp[x][0]+b-c;
        int t3=a+dp[x][1]-2*c;
    
        ans[x]=max(t1,max(t2,t3));
    
        int SZ=G[x].size();
    
        for(int i=0;i<SZ;i++)
        {
            int id=G[x][i],to=e[id].v;
            if(flag[to]) continue;
            int na=0,nb=0,dp0=0,dp1=0, x1=0,x2=0,y1=0,y2=0;
            if(i-1>=0) x1=t[0][x][0][i-1];
            if(SZ-1-(i+1)>=0) x2=t[1][x][0][SZ-1-(i+1)];
            if(i-1>=0) y1=t[0][x][1][i-1];
            if(SZ-1-(i+1)>=0) y2=t[1][x][1][SZ-1-(i+1)];
            dp0=x1+x2; if(x1!=0&&x2!=0) dp0=dp0-v[x];
            int k1,k2;
            k1=x1+y2;  if(x1!=0&&y2!=0) k1=k1-v[x];
            k2=x2+y1;  if(x2!=0&&y1!=0) k2=k2-v[x];
            dp1=max(k1,k2);
            dp0=max(dp0,v[x]); dp1=max(dp1,v[x]);
            na=max(dp0,dp0-2*c+a); nb=max(dp1,max(dp0+b-c,a+dp1-2*c));
            get(to,na,nb,e[id].w);
    
        }
    
    }
    
    int main()
    {
        scanf("%d",&T); int cas=1;
        while(T--)
        {
            scanf("%d",&n); sz=0;
    
            memset(dp,0,sizeof dp);
            for(int i=0;i<=n;i++)
            {
                G[i].clear();
                t[0][i][0].clear(); t[0][i][1].clear();
                t[1][i][0].clear(); t[1][i][1].clear();
            }
    
            for(int i=1;i<=n;i++) scanf("%d",&v[i]);
            for(int i=1;i<=n-1;i++)
            {
                int u,v,w; scanf("%d%d%d",&u,&v,&w);
                add(u,v,w); add(v,u,w);
            }
    
            memset(flag,0,sizeof flag); dfs(1,0);
            memset(flag,0,sizeof flag); dfs(1,1);
    
            memset(flag,0,sizeof flag); get(1,0,0,0);
    
            printf("Case #%d:
    ",cas++);
            for(int i=1;i<=n;i++) printf("%d
    ",ans[i]);
        }
        return 0;
    }
  • 相关阅读:
    GridView固定表头
    图片自动适应大小
    GridView实现用"..."代替超长字符串
    使用纯 CSS 设计3D按钮
    Net下二进制形式的文件(图片)的存储与读取
    repeater创建复杂的表头
    GridView加入自动求和求平均值小计
    CSS+DIV(盒子)
    DIV 在 IE 与 FF 下的设置
    gridView分页
  • 原文地址:https://www.cnblogs.com/zufezzt/p/5786147.html
Copyright © 2011-2022 走看看