dp[i][j]表示为在i结点上选择j个节点的最大值
转移方程:dp[u][j+k]=max(dp[u][j+k],dp[u][j]+dp[v][k]);//在i的结点上选择j+k的的值为 max(在i结点上选择j+k个结点的值,在i结点上选j个结点+在i的儿子结点v上选择k个结点的值)
#include <iostream>
#include <cstdio>
#include <memory.h>
using namespace std;
const int maxn=203;
struct edge
{
int v,next;
}es[maxn];
int head[maxn],w[maxn],dp[maxn][maxn],n,m;
int dfs(int u){
dp[u][1]=w[u];
int tot=1;
for (int ne=head[u];ne!=-1;ne=es[ne].next){
int v=es[ne].v;
tot+=dfs(v);
for (int j=tot+1;j>=1;--j){//因为加了个超级原点,所以总数+1
for (int k=1;j+k<=tot;++k){
dp[u][j+k]=max(dp[u][j+k],dp[u][j]+dp[v][k]);//在i的结点上选择j+k的的值为 max(在i结点上选择j+k个结点的值,在i结点上选j个儿子结点+在i的儿子结点v上选择k个儿子结点的值)
}
}
}
return tot;
}
int main(){
while (scanf("%d%d",&n,&m)){
if(!n&&!m)break;
memset(head,-1,sizeof(head));
memset(dp,0,sizeof(dp));
int eidx=0;
for (int i=1;i<=n;++i){
int v;
scanf("%d%d",&v,&w[i]);
es[eidx].v=i;
es[eidx].next=head[v];
head[v]=eidx++;
}
dfs(0);
printf("%d\n",dp[0][m+1]);
}
return 0;
}