1. 程式人生 > >POJ 2486 Apple Tree(樹形DP)

POJ 2486 Apple Tree(樹形DP)

Apple Tree(樹形DP)

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int M = 210;
int wi[M];
int dp[M][M][2];//0回來,1不回來
int n, m;
int len;

struct Edge {
    int to, nxt;
} edge[M*2];

int head[M];
void add_edge(int u, int v) {
    edge[len].to = v;
    edge[len].nxt = head[u];
    head[u] = len++;
}

int vis[M];

void dfs(int rt) {
    vis[rt] = 1;
    for(int i = 0; i <= m; i++)
        dp[rt][i][0] = dp[rt][i][1] = wi[rt];

    for(int i = head[rt]; i != -1; i = edge[i].nxt) {
        int t = edge[i].to;
        if(vis[t])
            continue;

        dfs(t);
        for(int j = m; j >= 1; j--) {
            for(int k = 1; k <= j; k++) {
                /*
                dp[i][j][0]表示從i節點出發最後回到i節點花費最多j步能獲得的最大值,
                dp[i][j][1]表示從i節點出發最後不回到i節點花費最多j步能獲得的最大值
                dp[root][j][0] = max(dp[root][j-k][0] + dp[son][k-2][0])
                //root->son 和 son->root 共花費2步,j-k是在其他兒子花費的步數
                dp[root][j][1] = max(dp[root][j-k][0] + dp[son][k-1][1])
                dp[root][j][1] = max(dp[root][j-k][1] + dp[son][k-2][0])
                //只需要回到root一次,一種情況是先走其他兒子回到root再走son,
                //另一種情況是先走son這個兒子並回到root再去走其他兒子
                */
                dp[rt][j][0] = max(dp[rt][j][0], dp[rt][j-k][0]+dp[t][k-2][0]);
                dp[rt][j][1] = max(dp[rt][j][1], dp[rt][j-k][0]+dp[t][k-1][1]);
                dp[rt][j][1] = max(dp[rt][j][1], dp[rt][j-k][1]+dp[t][k-2][0]);
            }
        }
    }
}

int main() {
    //freopen("data.in", "r", stdin);
    int a, b;
    while(scanf("%d%d", &n, &m) != EOF) {
        memset(dp, 0, sizeof(dp));
        len = 0;
        memset(head, -1, sizeof(head));
        memset(vis, 0, sizeof(vis));
        for(int i = 1; i <= n; i++)
            scanf("%d", &wi[i]);
        for(int i = 1; i <= n-1; i++) {
            scanf("%d%d", &a, &b);
            add_edge(a, b);
            add_edge(b, a);
        }

        dfs(1);
        printf("%d\n", max(dp[1][m][0], dp[1][m][1]));
    }
    return 0;
}