POJ 2486 Apple Tree(樹形DP)
阿新 • • 發佈:2018-11-08
#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; }