分析:攻下一座城堡的前提是要先攻下它的前驱城堡,建立一个以0为根结点的树,他的权值为0
dp(i,j)表示以i为根结点去j个的最大值。
dp(i,1) = v[i] (v[i]为攻下i城堡获得的宝藏)
对与u结点取j+1个,可以转化为以孩子i为根取k个+以自己为根取j+1-k个和自己取j+1个的最大值 (为什么是j+1,因为建立了一个虚拟结点0,所以即使攻下某一城堡不需要先攻下其中一个城堡时,也要攻下0号虚拟城堡,但是不增加宝藏值)
dp[u][j+1] = max(dp[u][j+1],dp[u][j-k+1]+dp[Map[u][i]][k]); //dp[u][j-k+1]:其他孩子的总值 dp[Map[u][i]][k]:第i个孩子取k个
#include <bits/stdc++.h>
using namespace std;
const int maxn = 205;
vector<int> Map[maxn];
int dp[maxn][maxn]; //dp(i,j)表示以i为根结点时取j个所能达到的最大值
int v[maxn];
void dfs(int u,int num){
dp[u][1] = v[u];
for(int i = 0;i < Map[u].size();i++){
if(num > 1)
dfs(Map[u][i],num-1);
for(int j = num;j >= 1;j--){
for(int k = 1;k <= j;k++){
dp[u][j+1] = max(dp[u][j+1],dp[u][j-k+1]+dp[Map[u][i]][k]); //dp[u][j-k+1]:其他孩子的总值 dp[Map[u][i]][k]:第i个孩子去k个
}
}
}
}
int main(){
int n,m;
int a,b;
while( scanf("%d%d",&n,&m) && (n||m)){
memset(v,0,sizeof(v));
memset(dp,0,sizeof(dp));
for(int i = 0;i <= n;i++)
Map[i].clear();
for(int i = 1;i <= n;i++){
scanf("%d%d",&a,&v[i]);
Map[a].push_back(i);
}
dfs(0,m+1);
printf("%d\n",dp[0][m+1]);
}
return 0;
}