洛谷-P1352 没有上司的舞会
题目
给一颗树,n 个节点,每个点都有权值,选了一个节点,那么它的儿子们就不能被选。求选取一部分节点后权值最大多少?
分析
树形dp,用记忆化搜索。
d
p
[
x
]
[
0
]
dp[x][0]
dp[x][0] 表示以
x
x
x 节点为跟的子树,不选
x
x
x 节点 情况下,最大权值。
d
p
[
x
]
[
1
]
dp[x][1]
dp[x][1] 表示以
x
x
x 节点为跟的子树,选
x
x
x 节点 情况下,最大权值。
dfs 搜一下填数组
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 9999991;
const int N = 6e3 + 10;
int n, x, y, r;
int val[N], rt[N], dp[N][2];
vector<int> son[N];
void DP(int rt){
dp[rt][0] = 0; //不选自己
dp[rt][1] = val[rt]; //选自己
for(auto x : son[rt]){
DP(x); //利用儿子更新自己之前先把儿子求出来
dp[rt][0] += max(dp[x][0], dp[x][1]);
dp[rt][1] += dp[x][0];
}
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++){
scanf("%d", &val[i]);
}
for(int i = 1; i <= n; i++){
scanf("%d%d", &x, &y);
rt[x] = 1; //有上司
son[y].push_back(x);
}
for(int i = 1; i <= n; i++){ //找根节点
if(!rt[i]){
r = i;
break;
}
}
DP(r);
printf("%d\n", max(dp[r][1], dp[r][0]));
return 0;
}