题目描述
某大学有N个职员,编号为1~N。他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数Ri,但是呢,如果某个职员的上司来参加舞会了,那么这个职员就无论如何也不肯来参加舞会了。所以,请你编程计算,邀请哪些职员可以使快乐指数最大,求最大的快乐指数。
输入输出格式
输入格式:
第一行一个整数N。(1<=N<=6000)
接下来N行,第i+1行表示i号职员的快乐指数Ri。(-128<=Ri<=127)
接下来N-1行,每行输入一对整数L,K。表示K是L的直接上司。
最后一行输入0 0
输出格式:
输出最大的快乐指数。
输入输出样例
输入样例#1
7 1 1 1 1 1 1 1 1 3 2 3 6 4 7 4 4 5 3 5 0 0
输出样例#1
5
思路
超级棒的树形dp题目。
令dp[i][0]为以i为根的子树,且如果i不参加的最大快乐值;dp[i][1]为以i为根的子树,且如果i参加的最大快乐值。
显然,如果你不去,那你的下属想去就去。
dp[i][0]=sum(max(dp[son][0],dp[son][1])) 其中son是i的儿子
显然,如果你去了,那你的下属肯定不能去。
dp[i][1]=sum(dp[son][0])+happy[i] 其中son是i的儿子
答案为max(dp[root][0],dp[root][1])。
#include <stdio.h>
#include <iostream>
#include <vector>
using namespace std;
int happy[6001],a[6001],dp[6001][2],n,m,s;
bool vis[6001];
vector<int> son[6001];
void dfs(int i)
{
register int j;
dp[i][0]=0;
dp[i][1]=happy[i];
for(j=0;j<son[i].size();j++)//遍历所有儿子节点
{
int Son=son[i][j];
dfs(Son);
dp[i][0]+=max(dp[Son][0],dp[Son][1]);
dp[i][1]+=dp[Son][0];
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
register int i,j;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>happy[i];
}
for(i=1;i<=n-1;i++)//叶子节点没有儿子
{
int fa,Son;
cin>>Son>>fa;
son[fa].push_back(Son);
vis[Son]=1;
}
int root;
for(i=1;i<=n;i++)//找根
{
if(vis[i]==0)
{
root=i;
break;
}
}
dfs(root);
cout<<max(dp[root][0],dp[root][1])<<endl;
return 0;
}