[洛谷-P2014] [CTSC1997] 选课(树形背包DP)
创始人
2024-06-01 12:06:12
0

[洛谷-P2014] [CTSC1997] 选课

  • 一、问题
    • 题目描述
    • 输入格式
    • 输出格式
    • 样例 #1
      • 样例输入 #1
      • 样例输出 #1
  • 二、分析
  • 三、代码

一、问题

题目描述

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

输入格式

第一行有两个整数 NNN , MMM 用空格隔开。( 1≤N≤3001 \leq N \leq 3001≤N≤300 , 1≤M≤3001 \leq M \leq 3001≤M≤300 )

接下来的 NNN 行,第 I+1I+1I+1 行包含两个整数 $k_i $和 sis_isi​, kik_iki​ 表示第I门课的直接先修课,sis_isi​ 表示第I门课的学分。若 ki=0k_i=0ki​=0 表示没有直接先修课(1≤ki≤N1 \leq {k_i} \leq N1≤ki​≤N , 1≤si≤201 \leq {s_i} \leq 201≤si​≤20)。

输出格式

只有一行,选 MMM 门课程的最大得分。

样例 #1

样例输入 #1

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

样例输出 #1

13

二、分析

这道题是一道很典型的树形背包DP问题的模板题目。这道题唯一需要注意的是,由于每个课都有一个先选课。所以最终这些课程之间的关系会构成一个森林,但是我们的树形DP是在一棵树上进行的,所以我们需要将这些割裂的子树用一个节点统一起来,我们把这个这节点编号为000,这个根叫做超根
那么这个超根我们是要选择的,只不过它对答案的贡献是0。也就是说我们需要选择的是M+1M + 1M+1个节点。

如果不懂树形背包DP的话,可以看作者之前的文章,讲解很详细:AcWing 10. 有依赖的背包问题(分组背包问题 + 树形DP)

三、代码

这里写的是空间优化后的代码。

#include
#define endl '\n'
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef pair pii;
const int N = 300+ 10;
vectoredge[N];
int f[N][N];
int score[N];
int n, m;void dp(int u, int M)
{f[u][1] = score[u];for(int i = 0; i < edge[u].size(); i ++ ){int son = edge[u][i];dp(son, M - 1);for(int j = M; j >= 0; j -- ){for(int q = 0; q <= j - 1; q ++ ){f[u][j] = max(f[u][j - q] + f[son][q], f[u][j]);}}}
}void solve()
{cin >> n >> m;for(int i = 0; i < n; i ++ ){int x, y;cin >> x >> y;score[i + 1] = y;edge[x].push_back(i + 1);}dp(0, m + 1);cout << f[0][m + 1] << endl;
}int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);solve();
}

相关内容

热门资讯

中证A500ETF摩根(560... 8月22日,截止午间收盘,中证A500ETF摩根(560530)涨1.19%,报1.106元,成交额...
A500ETF易方达(1593... 8月22日,截止午间收盘,A500ETF易方达(159361)涨1.28%,报1.104元,成交额1...
何小鹏斥资约2.5亿港元增持小... 每经记者|孙磊    每经编辑|裴健如 8月21日晚间,小鹏汽车发布公告称,公司联...
中证500ETF基金(1593... 8月22日,截止午间收盘,中证500ETF基金(159337)涨0.94%,报1.509元,成交额2...
中证A500ETF华安(159... 8月22日,截止午间收盘,中证A500ETF华安(159359)涨1.15%,报1.139元,成交额...
科创AIETF(588790)... 8月22日,截止午间收盘,科创AIETF(588790)涨4.83%,报0.760元,成交额6.98...
创业板50ETF嘉实(1593... 8月22日,截止午间收盘,创业板50ETF嘉实(159373)涨2.61%,报1.296元,成交额1...
港股异动丨航空股大幅走低 中国... 港股航空股大幅下跌,其中,中国国航跌近7%表现最弱,中国东方航空跌近5%,中国南方航空跌超3%,美兰...
电网设备ETF(159326)... 8月22日,截止午间收盘,电网设备ETF(159326)跌0.25%,报1.198元,成交额409....
红利ETF国企(530880)... 8月22日,截止午间收盘,红利ETF国企(530880)跌0.67%,报1.034元,成交额29.0...