poj 2324 Anniversary party(树形DP)

/*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);
	}
}

  

原文地址:https://www.cnblogs.com/td15980891505/p/5796786.html