- 新年就要来临啦,小猴腮雷一家
人将作为嘉宾被邀请到了春晚上。然而小猴腮雷的一家都曾经是大名鼎鼎的熊孩子,无论在什么时候都会,也只会和自己的直系亲属,也就是父母吵架,当然,即便是在春晚这个舞台上也是这样。
- 为了到时候不会引起战争,组委会据此思考到底要邀请哪些人?更让组委会头疼是,每个猴腮雷拥有一个活泼值,组委会既想要他们不会发生矛盾,也想尽量让来参加的猴腮雷活泼值的和最大.
- 第一行一个整数
- 接下来 行,第 行表示 号猴腮雷的活泼值 。
- 接下来 行,每行输入一对整数 。表示 和 是直接亲属关系。
- 最后一行输入 。
样例输入
7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
0 0
样例输出
- 对于 的数据 。
- 对于 的数据 。
题解
- 裸的树型 dp,和 没有上司的舞会 完全相同。
- 我们只需定义 dp[i][0/1] :表示以 i 为根的子树,不选/选 i 的最大活跃度。
- dp[i][0]=∑son∈imax(dp[son][0],dp[son][1])。
- dp[i][1]=∑son∈idp[i][0] 。
code1
using namespace std;
const int maxn = 6010;
struct Edge {
int next, to;
} edge[maxn];
int head[maxn], dp[maxn][3], a[maxn], n;
int tot = 0;
void add(int x, int y) {
edge[++tot].to = y;
edge[tot].next = head[x];
head[x] = tot;
}
void tree_dp(int root) {
dp[root][0] = 0;
dp[root][1] = a[root];
for (int x = head[root]; x; x = edge[x].next) {
tree_dp(edge[x].to);
dp[root][0] += max(dp[edge[x].to][0], dp[edge[x].to][1]);
dp[root][1] += dp[edge[x].to][0];
}
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
int root = 1;
for (int i = 1; i < n; i++) {
int x, y;
cin >> x >> y;
if (root == x)
root = y;
add(y, x);
}
int x, y;
cin >> x >> y;
tree_dp(root);
cout << max(dp[root][0], dp[root][1]);
return 0;
}
code2
#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;
}