P2014 [CTSC1997]选课

题目链接 https://www.luogu.com.cn/problem/P2014

题目描述

在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习。现在有 NN 门功课,每门课有个学分,每门课有一门或没有直接先修课(若课程 a 是课程 b 的先修课即只有学完了课程 a,才能学习课程 b)。一个学生要从这些课程里选择 MM 门课程学习,问他能获得的最大学分是多少?

输入

7  4
2  2
0  1
0  4
2  1
7  1
7  6
2  2

输出

13
#include <iostream>
using namespace std;
const int maxn = 6 * 1e3 + 10;
int n,m,num;
int dp[maxn][305],head[maxn];

struct node {
    int to, next;
} ed[maxn];

void add(int x, int y) {
    ed[++num].next = head[x];
    ed[num].to = y;
    head[x] = num;
}

//tree_dp(x)的作用就是算出以x为节点时,分别选0~m个节点各自的最大值
void tree_dp(int x) {
    for (register int i = head[x]; i; i = ed[i].next) {
        int v = ed[i].to;
        tree_dp(v);
        //倒序枚举,使用 to 节点的 f 数组更新 x 节点的 f 数组
        for(register int j=m;j>=1;--j) {
            for(register int k=1;k<=j-1;++k) {
                dp[x][j]=max(dp[x][j],dp[x][j-k]+dp[v][k]);
            }
        }
    }
}

int main() {
    cin >> n >> m;
    for(register int i=1,a;i<=n;++i) {
        cin>>a>>dp[i][1];
        add(a,i);
    }
    m++;  // 由于 0 号节点的参与,m 需要自加1
    tree_dp(0);
    cout << dp[0][m] << endl;
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值