链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
Ural大学有N名职员,编号为1~N。
他们的关系就像一棵以校长为根的树,父节点就是子节点的直接上司。
每个职员有一个快乐指数,用整数 HiHi 给出,其中 1≤i≤N,1≤i≤N1\leq i\leq N,1\leq i\leq N1≤i≤N,1≤i≤N。
现在要召开一场周年庆宴会,不过,没有职员愿意和直接上司一起参会。
在满足这个条件的前提下,主办方希望邀请一部分职员参会,使得所有参会职员的快乐指数总和最大,求这个最大值。
题解:本题的实质就是求最大独立集的权值之和的最大值
确定状态:f[i][0]表示i这个点不选时i点及其子树的最大权值
f[i][1]表示i这个点选中时i点及其子树的最大权值
状态转移方程:
f[i][0]=MAX(f[j][0],f[j][1])j为i的子结点
f[i][1]=h[i]+f[j][0]
边界条件:
f[i][0]=0 f[i][1]=h[i]
结果就是max(f[root][0],f[root][1])
那么如何找出这个根结点的值呢?我们发现一颗n个结点的树有n-1条边,这n-1个父子关系中没有出现过作为子节点的点就是根结点,具体实现参照代码
#include<bits/stdc++.h>
using namespace std;
int n;
int h[6200];
vector<int>son[6100];
int f[6100][2];
void dfs(int i)
{
f[i][0]=0;
f[i][1]=h[i];
for(int x=0;x<son[i].size();x++)
{
int j=son[i][x];
dfs(j);
f[i][0]+=max(f[j][0],f[j][1]);
f[i][1]+=f[j][0];
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>h[i];
}
int root=n*(n+1)/2;
for(int i=1;i<n;i++)
{
int x,y;
cin>>x>>y;
son[y].push_back(x);
root-=x;
}
dfs(root);//从根开始搜
cout<<max(f[root][0],f[root][1]);
return 0;
}