这个是我的第一道树型DP的题 解题思路: 首先添加一个0节点这样可以简化. 根据子节点用多重背包算出根节点 代码: /* ID: mnlm1991 PROG: hdoj 1561 the more the better LANG: C++ */ #include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<vector> #include<algorithm> #include<string> #include<map> #include<set> #include<bitset> #include<queue> #include<iostream> using namespace std; const int MaxN = 202; int son[MaxN]; int brother[MaxN]; int value[MaxN]; int dp[MaxN][MaxN]; void Init() { memset(brother, -1, sizeof(brother)); memset(son, -1, sizeof(son)); value[0] = 0; memset(dp, 0, sizeof(dp)); return; } void Insert(int x, int y, int i) { value[i] = x; if (son[y] == -1) { son[y] = i; } else { y = son[y]; while (brother[y] != -1) { y = brother[y]; } brother[y] = i; } return; } int Deal(int i, int M) { int k; int ret = 0; int v[MaxN]; int w[MaxN]; int cnt; int j; int x; for (x = son[i]; x != -1; x = brother[x]) { cnt = Deal(x, M - 1); for (j = M - 1; j > 0; j--) { for (k = 1; k <= cnt && k <= j; k++) { dp[i][j] = max(dp[i][j], dp[i][j - k] + dp[x][k]); } } ret += cnt; } for (k = M; k > 0; k--) { dp[i][k] = dp[i][k - 1] + value[i]; } return ret + 1; } int main() { int N, M; while (scanf("%d%d", &N, &M), N || M) { Init(); int i; int vv; int f; for (i = 1; i <= N; i++) { scanf("%d%d", &f, &vv); Insert(vv, f, i); } Deal(0, M + 1); printf("%d/n", dp[0][M + 1]); } return 0; }