Magic boy Bi Luo with his excited tree (树形dp)

Bi Luo is a magic boy, he also has a migic tree, the tree has NN nodes , in each node , there is a treasure, it's value is V[i]V[i], and for each edge, there is a cost C[i]C[i], which means every time you pass the edge ii , you need to pay C[i]C[i]. 

You may attention that every V[i]V[i] can be taken only once, but for some C[i]C[i] , you may cost severial times. 

Now, Bi Luo define ans[i]ans[i] as the most value can Bi Luo gets if Bi Luo starts at node ii. 

Bi Luo is also an excited boy, now he wants to know every ans[i]ans[i], can you help him?

InputFirst line is a positive integer T(T104)T(T≤104) , represents there are TT test cases. 

Four each test: 

The first line contain an integer NN(N105)(N≤105). 

The next line contains NN integers V[i]V[i], which means the treasure’s value of node i(1V[i]104)i(1≤V[i]≤104). 

For the next N1N−1 lines, each contains three integers u,v,cu,v,c , which means node uuand node vv are connected by an edge, it's cost is c(1c104)c(1≤c≤104). 

You can assume that the sum of NN will not exceed 106106.
OutputFor the i-th test case , first output Case #i: in a single line , then output NNlines , for the i-th line , output ans[i]ans[i] 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

# 1 Case: 
15 
10 
14 
9 
15 

SOLUTION:
This is considered a more difficult dp it,
it is easy to think of dp i 0/1 representatives only consider returning to the sub-tree i will not the greatest value to the root node,
after at this time, we must consider the transfer
after obtaining dp, dp array of the most difficult step is to transform a tree root to change the time, I feel the problem solution online well written

CODE:
//
//  Created by Running Photon
//  Copyright (c) 2015 Running Photon. All rights reserved.
//
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <sstream>
#include <set>
#include <vector>
#include <stack>
#define ALL(x) x.begin(), x.end()
#define INS(x) inserter(x, x,begin())
#define ll long long
#define CLR(x) memset(x, 0, sizeof x)
using namespace std;
const int inf = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 2e5 + 10;
const int maxv = 1e5 + 10;
const double eps = 1e-9;

int pnt[maxn], nxt[maxn], val[maxv], head[maxv], cost[maxn], cnt;
void add_edge(int u, int v, int value) {
    pnt[cnt] = v;
    cost[cnt] = value;
    nxt[cnt] = head[u];
    head[u] = cnt++;
}
int dp[2][maxv];
void dfs1(int u, int fa) {
    dp[0][u] = val[u];
    dp[1][u] = val[u];
    for(int i = head[u]; ~i; i = nxt[i]) {
        int v = pnt[i];
        if(v == fa) continue;
        dfs1(v, u);
        if(dp[0][v] - cost[i] * 2 > 0) {
            dp[0][u] += dp[0][v] - cost[i] * 2;
        }
    }
    for(int i = head[u]; ~i; i = nxt[i]) {
        int v = pnt[i];
        if(v == fa) continue;
        if(dp[0][u] - max(0, dp[0][v] - cost[i] * 2) + (dp[1][v] - cost[i]) >= dp[1][u]) {
            dp[1][u] = dp[0][u] - max(0, dp[0][v] - cost[i] * 2) + (dp[1][v] - cost[i]);
        }
    }
}
void dfs2(int u, int fa, int Cost) {
    int dir = u, tmp;
    if(fa != -1 && dp[0][fa] - Cost * 2 > 0) {
        dp[0][u] += dp[0][fa] - Cost * 2;
    }

    tmp = dp[1][u] = dp[0][u];

    if(fa!=-1)
        for(int i=1;i<=1;i++) {
        int v = fa;

        if(dp[0][u] - max(0, dp[0][v] - Cost * 2) + (dp[1][v] - Cost) >= dp[1][u]) {
            dir = v;
            swap(tmp, dp[1][u]);
            dp[1][u] = dp[0][u] - max(0, dp[0][v] - Cost * 2) + (dp[1][v] - Cost);
        }
        else
            if(dp[0][u] - max(0, dp[0][v] - Cost * 2) + (dp[1][v] - Cost) >= tmp) {
            tmp = dp[0][u] - max(0, dp[0][v] - Cost * 2) + (dp[1][v] - Cost);
        }
    }

    for(int i = head[u]; ~i; i = nxt[i]) {
        int v = pnt[i];

        if(dp[0][u] - max(0, dp[0][v] - cost[i] * 2) + (dp[1][v] - cost[i]) >= dp[1][u]) {
            dir = v;
            swap(tmp, dp[1][u]);
            dp[1][u] = dp[0][u] - max(0, dp[0][v] - cost[i] * 2) + (dp[1][v] - cost[i]);
        }
        else if(dp[0][u] - max(0, dp[0][v] - cost[i] * 2) + (dp[1][v] - cost[i]) >= tmp) {
            tmp = dp[0][u] - max(0, dp[0][v] - cost[i] * 2) + (dp[1][v] - cost[i]);
        }
    }
    // printf("dp[0][%d] = %d dp[1][%d] = %d  tmp = %d\n", u, dp[0][u], u, dp[1][u], tmp);

    int L = dp[0][u], R = dp[1][u];
    for(int i = head[u]; ~i; i = nxt[i]) {
        int v = pnt[i];
        if(v == fa) continue;
        if(dp[0][v] - cost[i] * 2 > 0) {
            dp[0][u] = L - (dp[0][v] - cost[i] * 2);
        }
        if(dir == v) {
            dp[1][u] = tmp;
            if(dp[0][v] - cost[i] * 2 > 0) dp[1][u] -= (dp[0][v] - cost[i] * 2);
        }
        else if(dp[0][v] - cost[i] * 2 > 0) {
            dp[1][u] = R - (dp[0][v] - cost[i] * 2);
        }
        // printf("dir = %d\n", dir);
        // printf("nxt%d = %d\n", v, dp[1][u]);
        dfs2(v, u, cost[i]);
        dp[0][u] = L, dp[1][u] = R;
    }
}
int main() {

    int T;
    int cas = 0;
    scanf("%d", &T);
    while(T--) {
        int n;
        printf("Case #%d:\n", ++cas);
        scanf("%d", &n);
        cnt = 0;
        memset(head, -1, sizeof (int) * (n + 1));
        for(int i = 1; i <= n; i++) scanf("%d", val + i);
        for(int i = 1; i < n; i++) {
            int u, v, value;
            scanf("%d%d%d", &u, &v, &value);
            add_edge(u, v, value);
            add_edge(v, u, value);
        }
        dfs1(1, -1);
        dfs2(1, -1, 0);
        for(int i = 1; i <= n; i++) {
            printf("%d\n", max(dp[0][i], dp[1][i]));
        }
    }

    return 0;
}
 

  












Guess you like

Origin www.cnblogs.com/zhangbuang/p/11371836.html