开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 31 天,点击查看活动详情
题目描述
Ural 大学有 N 名职员,编号为 1∼N。
他们的关系就像一棵以校长为根的树,父节点就是子节点的直接上司。
每个职员有一个快乐指数,用整数 给出,其中 1≤i≤N。
现在要召开一场周年庆宴会,不过,没有职员愿意和直接上司一起参会。
在满足这个条件的前提下,主办方希望邀请一部分职员参会,使得所有参会职员的快乐指数总和最大,求这个最大值。
输入格式
第一行一个整数 N。
接下来 N 行,第 i 行表示 i 号职员的快乐指数 。
接下来 N−1 行,每行输入一对整数 L,K,表示 K 是 L 的直接上司。
输出格式
输出最大的快乐指数。
数据范围
输入样例:
7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
输出样例:
5
题目分析
本题为树形DP的一个题目。
首先我们可以将所有职员以及他们之间的对应关系构造为一个树,每个树节点的父亲对应他的上司,树节点的儿子对应他的下属。
定义 表示第 个人来/不来,他以及他的下属所能获得的最大的快乐值。
当第 个职员不来时,对于他的下属的状态是随意的,即 f[i][0] += max(f[u][0], f[u][1])。
当第 个职员到来时,他的下属到来不会获得任何收益,反而会影响下属的下属,所以最好的情况是他的直接下属不来,即 f[i][1] += f[u][0],最后不要忘记 f[i][1] += w[i]。
每个职员的状态需要其下属的状态更新完后才可更新,可采用递归的方式由下到上得到答案。
Accept代码
#include <bits/stdc++.h>
using namespace std;
const int N = 6010;
int h[N], e[N], ne[N], idx;
int n, v[N], st[N], f[N][2];
void add(int a, int b)
{
e[++ idx] = b, ne[idx] = h[a], h[a] = idx;
}
void dfs(int u)
{
f[u][1] = v[u];
for (int i = h[u]; i; i = ne[i])
{
int ei = e[i];
dfs(ei);
f[u][0] += max(f[ei][0], f[ei][1]);
f[u][1] += f[ei][0];
}
// cout << u << ' ' << f[u][0] << ' ' << f[u][1] << "\n";
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i ++) cin >> v[i];
for (int i = 1; i < n; i ++)
{
int a, b;
cin >> a >> b;
add(b, a);
st[a] = 1;
}
int root = 1;
while (st[root]) root ++;
dfs(root);
cout << max(f[root][0], f[root][1]);
return 0;
}