hdu 5834 Magic boy Bi Luo with his excited tree 树形dp+转移 Magic boy Bi Luo with his excited tree

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1058    Accepted Submission(s): 308


Problem Description
Bi Luo is a magic boy, he also has a migic tree, the tree has ], can you help him?
 
Input
First line is a positive integer 6.
 
Output
For the i-th test case , first output Case #i: in a single line , then output ] in a single line.
 
Sample Input
1 5 4 1 7 7 7 1 2 6 1 3 1 2 4 8 3 5 2
 
Sample Output
Case #1: 15 10 14 9 15
 
Author
UESTC
 
Source
题意:给你一棵树,每个结点有个宝藏价值w,每次只能拿一次宝藏,每次经过路径需要花费val值,路径可以来回经过,同时可以多次花费val值,求从i点出发,能拿到的最大权值ans【i】
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <cmath>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <set>
#define MM(a,b) memset(a,b,sizeof(a));
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
#define CT continue
#define SC scanf
const int N=1e5+10;
int val[N],dp[N][6],ans[N];
struct edge{
   int v,c;
};
vector<edge> G[N];

void dfs1(int u,int f)
{
    dp[u][1]=dp[u][0]=val[u];
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].v,c=G[u][i].c;
        if(v==f) CT;
        dfs1(v,u);
        int cur=dp[u][0]-c+dp[v][1],
            ano1=dp[u][1]+max(dp[v][0]-2*c,0),
            ano2=dp[u][2]+max(dp[v][0]-2*c,0);
        if(cur>ano1){
            dp[u][4]=v;
            dp[u][1]=cur;
            dp[u][2]=ano1;
        }
        else if(cur>ano2)  {
            dp[u][1]=ano1;
            dp[u][2]=cur;
        }
        else{
            dp[u][1]=ano1;
            dp[u][2]=ano2;
        }
        dp[u][0]+=max(0,dp[v][0]-2*c);
    }
}

void dfs2(int u,int f,int fback,int fnback)
{
    ans[u]=max(dp[u][0]+fnback,dp[u][1]+fback);
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].v,c=G[u][i].c;
        if(v==f) CT;
        int uback=fback+dp[u][0]-max(0,dp[v][0]-2*c)-2*c,unback;
        if(v==dp[u][4]){
           unback=max(dp[u][0]-max(0,dp[v][0]-2*c)+fnback,
                      fback+dp[u][2]-max(0,dp[v][0]-2*c))-c;
        }
        else{
           unback=max(fnback+dp[u][0]-max(0,dp[v][0]-2*c),
                      fback+dp[u][1]-max(0,dp[v][0]-2*c))-c;
        }
        dfs2(v,u,max(0,uback),max(0,unback));
    }
}

int main()
{
    int cas,kk=0;
    SC("%d",&cas);
    while(cas--){
        int n;SC("%d",&n);
        MM(dp,0);
        for(int i=1;i<=n;i++){
            SC("%d",&val[i]);
            G[i].clear();
        }
        for(int i=1;i<=n-1;i++){
            int u,v,c;
            SC("%d%d%d",&u,&v,&c);
            G[u].push_back((edge){v,c});
            G[v].push_back((edge){u,c});
        }
        dfs1(1,-1);
        dfs2(1,-1,0,0);
        printf("Case #%d:
",++kk);
        for(int i=1;i<=n;i++) printf("%d
",ans[i]);
    }
    return 0;
}

 题解: