/*poj 2324 Anniversary party(树形DP) ---用dp[i][1]表示以i为根的子树节点i要去的最大欢乐值,用dp[i][0]表示以i为根节点的子树i不去时的最大欢乐值, ---于是当i去时,i的所有儿子都不能去:dp[i][1]=sum(dp[j][0])+a[i],其中j是i的儿子节点。 ---当i不去时,i的儿子可去也可不去:dp[i][0]=sum(max(dp[j][0],dp[j][1])),j是i的儿子节点 ---边界条件:当i时叶子节点时,dp[i][1]=a[i],dp[i][0]=0; */ #define _CRT_SECURE_NO_DEPRECATE #include<iostream> #include<vector> #include<algorithm> using namespace std; const int maxn = 6000 + 5; int a[maxn], dp[maxn][2]; vector<int>vec[maxn]; //记忆化搜索 int dfs(int u, int k){ if (dp[u][k] >= 0)return dp[u][k]; int n = vec[u].size(); if (k == 0)dp[u][k] = 0; else dp[u][k] = a[u]; for (int i = 0; i < n; i++){ int v = vec[u][i]; if (k == 0) dp[u][0]+=max(dfs(v, 1), dfs(v, 0)); else dp[u][1] += dfs(v, 0); } return dp[u][k]; } int main(){ int n,i,u,v; while (scanf("%d%d", &n, &a[1])&&n){ for (i = 0; i <= n; i++) vec[i].clear(); for (i = 2; i <= n; i++)scanf("%d", &a[i]); for (i = 1; i < n; i++){ scanf("%d%d", &u, &v); vec[v].push_back(u); } memset(dp, -1, sizeof(dp)); int ans = -1; for (i = 1; i <= n; i++) ans = max(ans, max(dfs(i, 0), dfs(i, 1))); printf("%d ", ans); } }