人生第一道树形dp~~~
dp[i][j] 表示以i为根节点放j 个的价值,注意因为子节点对父节点是有依赖的,所以如果要放子节点那么一定要放父节点。
然后我设置一个0号节点为根节点,那么全部节点就能构成一棵树。因为如果放其他节点的话,0号节点也一定要放,所以我们要求的就是dp[0][m + 1]。
#include <iostream>
#include<stdio.h>
#include<cstring>
using namespace std;
int a[210]; //价值
int b[210][210]; //子节点
int dp[210][210]; //dp[i][j]表示已i为根节点放j 个的价值
int n,m;
void dfs(int root)
{
for(int i = 1;i <= b[root][0];i++)
{
int cur = b[root][i];
if(b[root][0] != 0) dfs(cur);
}
for(int i = 1;i <= b[root][0];i++)
for(int j = m+1;j >= 1; j--) //当前背包容量,倒序遍历,dp省一个维度
{
for(int k = 1;k<= j - 1;k++) //从当前节点的子节点取k个,k只能从1到j - 1,因为要剩一个单位放父节点
{
dp[root][j] = max(dp[root][j],dp[root][j - k] + dp[b[root][i]][k]);
}
}
}
int main()
{
while(scanf("%d %d",&n,&m)!= EOF)
{
if(n + m == 0) break;
memset(b,0,sizeof b);
memset(dp,0,sizeof dp);
for(int i = 1;i <= n;i++)
{
int temp;
scanf("%d %d",&temp,&a[i]);
int num = ++b[temp][0];
b[temp][num] = i;
dp[i][1] = a[i];
}
dp[0][1] = 0; //放0号节点获得的价值初始化为0
dfs(0);
printf("%d\n",dp[0][m+1]);
}
return 0;
}