POJ2342.Anniversary party(树状DP)

题目链接:https://vjudge.net/contest/373128#problem/D
题意:周年纪念日聚会,n个人组成以校长为首的一颗树,每个人都有对应的欢乐度和与其他的上下级关系,在任意两个人没有直接上下级关系的情况下,求最大的欢乐度
解题思路:
利用vector数组son和数组father来保存上下级关系
dp[i][0]表示第i个人不来的最大欢乐度情况
dp[i][1]表示第i个人来的最大欢乐度情况
dp[i][0]+=max(dp[son][1],dp[son][0]),当第i个人不来的时候,他的下属可以来也可以不来
dp[i][1]+=dp[son][0],当第i个人来的时候,他的下属一定不会来

#include<iostream>
#include<cstdio>
#include<vector>
#include<string.h>
using namespace std;
int dp[6100][2];
int indegree[6100];
int father[6100];
int vis[6100];
int n;
vector<int> son[6000];
void tree_dp(int node)
{
	vis[node]=1;
	for(int i=0;i<indegree[node];i++){
		if(!vis[son[node][i]]){
		//先处理子问题
			tree_dp(son[node][i]);
			dp[node][1]+=dp[son[node][i]][0];
			dp[node][0]+=max(dp[son[node][i]][0],dp[son[node][i]][1]);
		}
	}
}
int main()
{
	while(scanf("%d",&n)!=EOF){
		memset(dp,0,sizeof(dp));
		memset(son,0,sizeof(son));
		memset(vis,0,sizeof(vis));
		memset(father,0,sizeof(father));
	    for(int i=1;i<=n;i++)  scanf("%d",&dp[i][1]);
	    int L,R;
	    int root=1;
	    bool flag=true;
	    while(scanf("%d%d",&L,&R),L+R){
			son[R].push_back(L);
		    indegree[R]++;
			father[L]=R;
	    }
	    //找到树的根节点
		while(father[root])
			root=father[root];
		tree_dp(root);
	    printf("%d\n",max(dp[root][0],dp[root][1]));
	}
	return 0;
}
原创文章 65 获赞 3 访问量 2078

猜你喜欢

转载自blog.csdn.net/littlegoldgold/article/details/106123351