题目链接: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;
}