分析:
显然题目给出的是一个树形结构(根结点是0)
设计状态:
f[i][j]
f
[
i
]
[
j
]
,表示
i
i
结点代表的子树,其中选择了个结点
那么在转移
f[i][j]
f
[
i
]
[
j
]
的时候,只要
j>1
j
>
1
,就可以将
j−1
j
−
1
合理的分配给
i
i
<script type="math/tex" id="MathJax-Element-361">i</script>的子结点
解决方法就是一个01背包
要注意如果子树要选,那么根结点一定选
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=205;
struct node{
int y,nxt;
};
node way[N<<1];
int st[N],tot=0,n,m,val[N],size[N],f[N][N];
void add(int u,int w) {
tot++;way[tot].y=w;way[tot].nxt=st[u];st[u]=tot;
}
void solve(int now) {
f[now][1]=val[now];
for (int l=st[now];l;l=way[l].nxt) //dfs子结点
{
solve(way[l].y);
for (int i=m;i>1;i--) //f[now][m]
for (int j=1;j<i;j++) //一定要选择根结点
f[now][i]=max(f[now][i],f[now][j]+f[way[l].y][i-j]);
}
}
int main()
{
while (scanf("%d%d",&n,&m)!=EOF&&n+m) {
memset(f,0,sizeof(f));
memset(st,0,sizeof(st)); tot=0;
for (int i=1;i<=n;i++) {
int x;
scanf("%d%d",&x,&val[i]);
add(x,i);
}
m++; //多加一个0结点
solve(0);
printf("%d\n",f[0][m]);
}
return 0;
}