易错点:
- 分组背包需要反向循环以保证状态转移的正确性.
- f[x][0]在dp前就初始化了,因此可以不枚举体积为0的情况.
- 注意初始化.
#include<cstdio>
#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
const int MAXN=500;
int f[MAXN][MAXN],score[MAXN];
vector<int> son[MAXN];
int m;
void dp(int x){
f[x][0]=0;
if(!son[x].empty()){
int size=son[x].size();
for(int i=0;i<size;i++){
int y=son[x].at(i);
dp(y);
for(int j=m;j>=1;j--){
for(int k=1;k<=j;k++){
f[x][j]=max(f[x][j],f[x][j-k]+f[y][k]);
}
}
}
}
if(x!=0){
for(int i=m;i>=1;i--){
f[x][i]=f[x][i-1]+score[x];
}
}
}
int main(){
memset(f,0xcf,sizeof(f));
int n;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
int fa,nowScore;
scanf("%d%d",&fa,&nowScore);
son[fa].push_back(i);
score[i]=nowScore;
}
dp(0);
printf("%d\n",f[0][m]);
return 0;
}