题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1561
题意不讲了,中文。
树形背包,可以以0为总root,m++。dp[i][j] 表示以i节点为root 攻克j个城堡的价值最大是多少。 dp[i][j] = max(dp[i][j] , dp[i.son][k] + dp[i][j - k])
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector> 5 using namespace std; 6 const int N = 205; 7 int dp[N][N], n, m, a[N]; 8 vector <int> G[N]; 9 10 void init(int n) { 11 for(int i = 0; i <= n; ++i) { 12 G[i].clear(); 13 } 14 memset(dp, 0, sizeof(dp)); 15 } 16 17 void dfs(int u, int p) { 18 for(int i = 1; i <= m; ++i) { 19 dp[u][i] = a[u]; 20 } 21 for(int i = 0; i < G[u].size(); ++i) { 22 int v = G[u][i]; 23 if(v == p) 24 continue; 25 dfs(v, u); 26 for(int j = m; j >= 1; --j) { //类似背包,倒着来取值可以唯一 27 for(int k = 1; k < j; ++k) { 28 dp[u][j] = max(dp[u][j], dp[v][j - k] + dp[u][k]); 29 } 30 } 31 } 32 } 33 34 int main() 35 { 36 while(~scanf("%d %d", &n, &m) && (n || m)) { 37 int u, v; 38 init(n); 39 for(int i = 1; i <= n; ++i) { 40 scanf("%d %d", &u, &v); 41 G[u].push_back(i); 42 a[i] = v; 43 } 44 ++m; 45 dfs(0, -1); 46 printf("%d ", dp[0][m]); 47 } 48 return 0; 49 }