[CTSC1997] 选课

[CTSC1997] 选课

人生中的第一道树形 \(DP\) .

这是一道树形 \(DP\) , 很显然, 这个题的课程关系是一个森林, 我们把 \(0\) 节点也算上, 就成了一棵树.

我们设状态 \(f[u][i]\) 表示以 \(u\) 为根节点的子树中选 \(i\) 个课程的最大学分.

转移: \(f[u][i] = max(f[v1][j1] + f[v2][j2] + ...)\) , \(\sum j = i\) .

\(code:\)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int read() {
    int x = 0, f = 1;
    char ch = getchar();
    while (!isdigit(ch)) {
        if (ch == '-') f = -1;
        ch = getchar();
    }
    while (isdigit(ch)) {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * f;
}
const int N = 305;
int n, m, f[N][N];
int tot, to[N], nxt[N], head[N];
void add(int u, int v) {
    to[++tot] = v, nxt[tot] = head[u], head[u] = tot;
}
void dfs(int x) {
    for (int i = head[x]; i; i = nxt[i]) {
        int y = to[i];
        dfs(y);
        for (int j = m; j >= 1; j--) {
            for (int k = 0; k < j; k++) {
                f[x][j] = max(f[x][j], f[y][k] + f[x][j - k]);
            }
        }
    }
}
int main() {
    n = read(), m = read() + 1;
    for (int i = 1; i <= n; i++) {
        int k = read(); f[i][1] = read();
        add(k, i);
    }
    dfs(0);
    printf("%d", f[0][m]);
    return 0;
}
posted @ 2021-08-24 08:24  sshadows  阅读(45)  评论(0编辑  收藏  举报