思路:树形结构 加一个点(0点)构成森林 然后树形dp。。。
状态转移方程:
dp[x][j] = max(dp[x][j], dp[cnt][j-i] + dp[x][i]);
表示第x个的子节点中取j个 为最优解 cnt为x的某个子节点
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#define N 10005<<1
#define INF 10000000
#define LL long long
#define eps 10E-9
#define mem(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,-1,sizeof(a))
#define w(a) while(a)
#define s(a) scanf("%d",&a)
#define ss(a,b) scanf("%d%d",&a,&b)
#define sss(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define PI acos(-1.0)
using namespace std;
int n, m;
int dp[202][202];
int i_th_son[202][202];
int num_son[202];
bool vis[202];
void tree_dp(int x){
vis[x] = true;
for(int i=1; i<=num_son[x]; i++){
int cnt = i_th_son[x][i];
if(!vis[cnt]) tree_dp(cnt);
for(int j=m; j>=2; j--){
for(int i=1; i<j; i++){
if(dp[cnt][j-i]>-1 && dp[x][i]>-1) dp[x][j] = max(dp[x][j], dp[cnt][j-i] + dp[x][i]);
}
}
}
}
int main(){
w(~ss(n,m) && (n||m)){
int a, b;
dp[0][1] = 0;
mem(num_son);
for(int i=1; i<=n; i++){
ss(a,b);
dp[i][1] = b;
i_th_son[a][++num_son[a]] = i;
}
m++;//加点
for(int i=0; i<=n; i++){
dp[i][0] = 0;
vis[i] = false;
for(int j=2; j<=m; j++){
dp[i][j] = -1;
}
}
tree_dp(0);
cout<<dp[0][m]<<endl;
}
return 0;
}