没有上司的舞会
题目描述
Ural 大学有 N 个职员,编号为 1~N。他们有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。每个职员有一个快乐指数。现在有个周年庆宴会,要求与会职员的快乐指数最大。但是,没有职员愿和直接上司一起与会。
输入格式
第一行一个整数 N。(1<=N<=6000)
接下来 N 行,第 i+1 行表示 i 号职员的快乐指数
接下来 N-1 行,每行输入一对整数 L,K。表示 K 是 L 的直接上司。
最后一行输入 0,0。
输出格式
输出最大的快乐指数。
样例
样例输入
7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
0 0
样例输出
5
题解
- 树形DP,十分明显!
- 找根节点方法:我们拿cnt[]数组来记录他的上司数目,只有根节点root没有上司,即
cnt[root]==0
; - dp[x][0/1]数组保存x为上司的子树,0和1为选择或不选择时的最大值。由此,状态转移方程显而易见:
dp[root][0]+=max(dp[tmp][1],dp[tmp][0]);
dp[root][1]+=dp[tmp][0];
- 最后判断并输出最大值,即
cout<<max(dp[i][1],dp[i][0]);
code
#include <bits/stdc++.h>
using namespace std;
const int maxn = 6500;
const int Inf = 0x3f3f3f3f;
int dp[maxn][maxn], jl[maxn];
int map_[maxn][maxn];
int r[maxn], tot[maxn], cnt[maxn];
int tmp, ans;
void tree_dp(int root) {
for (int i = 0; i < tot[root]; i++) {
int tmp = map_[root][i];
tree_dp(tmp);
dp[root][0] += max(dp[tmp][1], dp[tmp][0]);
dp[root][1] += dp[tmp][0];
}
dp[root][1] += r[root];
}
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> r[i];
}
int l, k;
for (int i = 1; i <= n; i++) {
cin >> l >> k;
map_[k][tot[k]++] = l;
cnt[l]++;
}
for (int i = 1; i <= n; i++)
if (cnt[i] == 0) {
tree_dp(i);
cout << max(dp[i][1], dp[i][0]);
return 0;
}
return 0;
}