[codevs1378]选课

传送门

对于具有树形依赖关系的背包问题,我们可以把每棵子树看作是一个泛化物品,那么一棵子树的泛化物品就是子树根节点的这件物品的泛化物品与由根所连的所有子树的泛化物品的和。

整个动规过程就是从叶子进行到根。

 1 #include<cstdio>
 2 #include<vector>
 3 #include<iostream>
 4 #define max(a, b) ((a) > (b) ? (a) : (b))
 5 using namespace std;
 6 
 7 inline void read(int &ans) {
 8     static char ch = getchar();
 9     register int neg = 1;
10     ans = 0;
11     for (; !isdigit(ch); ch = getchar())
12         if (ch == '-') neg = -1;
13     for (; isdigit(ch); ch = getchar())
14         ans = ans * 10 + ch - '0';
15     ans *= neg;
16 }
17 
18 const int N = 310;
19 int n, m;
20 vector < int > g[N];
21 int w[N], f[N][N];
22 
23 void dfs(int u, int c) {
24     if (c <= 0) return;
25     for (int i = 0; i < g[u].size(); ++i) {
26         int &v = g[u][i];
27         for (int j = 0; j < c; ++j) f[v][j] = f[u][j] + w[v];
28         dfs(v, c - 1);
29         for (int j = 1; j <= c; ++j)
30             f[u][j] = max(f[u][j], f[v][j - 1]);
31     }
32 }
33 
34 int main() {
35     read(n); read(m);
36     for (int u, i = 1; i <= n; ++i) read(u), g[u].push_back(i), read(w[i]);
37     dfs(0, m);
38     printf("%d\n", f[0][m]);
39     return 0;
40 }
View Code

 

题解见徐持衡《浅谈几类背包问题》

posted @ 2017-04-29 16:35  p0ny  阅读(149)  评论(0编辑  收藏  举报