链接
https://loj.ac/p/10154
题意
给出 $n$ 个带权节点,每个节点可能有父节点
如果你要选择一个节点,那么你也必须选择它的父节点
求选择 $m$ 个节点能得到最大权值是多少
思路
背包类树形 DP
$n$ 个节点构成了一个森林结构,构造一个 $0$ 节点让森铃转化以 $0$ 节点为根的树
将本题转化为分组背包模型:
对于节点 $x$,总体积为 $t$,有 $p=son(x)$ 组物品,每组物品有 $t-1$ 个,第 $i$ 组的第 $j$ 个物品体积为 $j$:
$dp[x][t]=w[x]+\max\limits_{t-1=\sum_{i=1}^{p}{c_i}} \sum_{i=1}^{p}{dp[son(x)_{i}][c_i]}$
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| #include<bits/stdc++.h> using namespace std; const int N=305; int n,m,w[N],dp[N][N]; vector<int>son[N]; void dfs(int u) { for(auto x:son[u]) { dfs(x); for(int t=m;t;t--) for(int j=1;j<=t;j++) dp[u][t]=max(dp[u][t],dp[u][t-j]+dp[x][j]); } if(u) for(int t=m;t;t--) dp[u][t]=dp[u][t-1]+w[u]; } int main() { ios::sync_with_stdio(false); cin.tie(0); cin>>n>>m; for(int i=1;i<=n;i++) { int a,b; cin>>a>>b; son[a].push_back(i); w[i]=b; } dfs(0); cout<<dp[0][m]<<endl; return 0; }
|