题意
公司年会,员工和中间领导构成一颗树。
每个点都有一个值,父子不可同时出现。求来的人的值最大。
(员工号1-N)先给出数字N(<=6000),后来是N行的员工值(-128~127)
接着是 N-1行的领导树的描述:L K 表示第K个员工是第L个员工的领导。
输入以0 0结束。
思路
- 建树。我们用father[L]=K保存即可。
- 所有人不来与来,用0/1表示,dp[i][0/1]表示员工i 不来/来,当前取得的最大值。
- 状态转移:
dp[i][0]:i不去时最大——他所有儿子们去/不去的最大值 相加
dp[i][1]:i有去是最大——他所有儿子们都不去的值 相加
AC代码
#include<iostream>
#include<string.h>
using namespace std;
const int maxn=6005;
int n;
int father[maxn],dp[maxn][2],vis[maxn];
void tree_dp(int root)
{
vis[root]=1;
for(int i=1;i<=n;i++)
{
if(!vis[i] && father[i]==root)
{
tree_dp(i);
dp[root][0]+=max(dp[i][0],dp[i][1]);
dp[root][1]+=dp[i][0];
}
}
}
int main()
{
while(cin>>n)
{
memset(dp,0,sizeof(dp));
memset(father,0,sizeof(father));
memset(vis,0,sizeof(vis));//用于标记,该点是否已经判断
for(int i=1;i<=n;i++)
{
cin>>dp[i][1];
}
int l,k,root;
while(cin>>l>>k,l||k)
{
father[l]=k;
root=k;
}
while(father[root])//找出树根
{
root=father[root];
}
tree_dp(root);
cout<<max(dp[root][0],dp[root][1])<<endl;//树根去/不去的最大值,也就是考虑所有情况最优解
}
return 0;
}