中文题。。。
树形dp第二发。
初看之下是形成多棵树,其实可以把0也看做根节点,没有限制的那些就当成0的孩子,然后可以打败的数目M+1,抵消掉0这个结点。然后就可以快乐地dfs了。
求值方面可以用背包的方法,用子节点去更新当前节点。具体方程式见代码吧。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int N = 210;
vector<int> V[N];
int n, m, w[N];
int dp[N][N];
void dfs(int x){
dp[x][0]=0;
for(int i=1; i<=m; i++) dp[x][i]=w[x];
for(int i=0; i<V[x].size(); i++){
int j = V[x][i];
dfs(j);
for(int k=m; k>1; k--){
for(int l=1; l<k; l++){
dp[x][k] = max(dp[x][k], dp[j][l]+dp[x][k-l]);
}
}
}
}
int main(){
while(~scanf("%d %d", &n, &m) && (n||m)){
m++;
for(int i=0; i<=n; i++) V[i].clear();
w[0]=0;
int a;
for(int i=1; i<=n; i++){
scanf("%d %d", &a, w+i);
V[a].push_back(i);
}
dfs(0);
printf("%d\n", dp[0][m]);
}
return 0;
}