洛谷P2014 [CTSC1997]选课
\(\large{题目链接}\)
\(\\\)
\(\Large{Solution: } \large{一道树形背包的题目,还是有所启示的。\\首先,注意到题目中可能有多棵树,不好进行\text{DFS}先建一个超级原点0,链接所有树根。\\设f[i][j]表示以i为根的树里选j个点的最大值,然后用子树更新根即可。\\注意在这段代码中}\)
\(\quad \quad \quad \quad \quad \quad\) \(\\\)
\(\quad \quad \quad \quad \quad \quad\) \(\large{要用选的选的个数少的答案去更新选的多的,所以j要倒序。\\最后,输出是f[0][m+1]。}\)
\(\quad \quad \quad \quad \quad \quad\)
\(\\\)
\(\Large\textbf{Code: }\)
#include <bits/stdc++.h>
#define gc() getchar()
#define LL long long
#define rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define _rep(i, a, b) for (int i = (a); i >= (b); --i)
using namespace std;
const int N = 305;
int n, m, cnt, head[N], size[N], f[N][N];
struct Edge {
int to, next;
}e[N << 1];
inline int read() {
int x = 0;
char ch = gc();
while (!isdigit(ch)) ch = gc();
while (isdigit(ch)) x = x * 10 + ch - '0', ch = gc();
return x;
}
inline void dfs1(int x) {
size[x] = 1;
for (int i = head[x]; i ; i = e[i].next) {
int u = e[i].to;
dfs1(u);
size[x] += size[u];
}
}
inline void dfs2(int x) {
for (int i = head[x]; i ; i = e[i].next) {
int u = e[i].to;
dfs2(u);
for (int j = size[x]; j >= 1; --j)
for (int k = 0; k < j; ++k)
f[x][j] = max(f[x][j], f[x][j - k] + f[u][k]);
}
}
inline void add(int x, int y) {
e[++cnt].to = y;
e[cnt].next = head[x];
head[x] = cnt;
}
int main() {
n = read(), m = read();
int x;
rep(i, 1, n) x = read(), f[i][1] = read(), add(x, i);
dfs1(0);
dfs2(0);
printf("%d\n", f[0][m + 1]);
return 0;
}