# [CTSC1997] 选课
## 题目描述
在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习。现在有 $N$ 门功课,每门课有个学分,每门课有一门或没有直接先修课(若课程 a 是课程 b 的先修课即只有学完了课程 a,才能学习课程 b)。一个学生要从这些课程里选择 $M$ 门课程学习,问他能获得的最大学分是多少?
## 输入格式
第一行有两个整数 N , $ 用空格隔开。M,N<300
接下来的 N$行,第 I+1 行包含两个整数 k_i 和 s_i, k_i 表示第I门课的直接先修课,s_i表示第I门课的学分。若 k_i=0 表示没有直接先修课
## 输出格式
只有一行,选 M 门课程的最大得分。
## 样例 #1
### 样例输入 #1
```
7 4
2 2
0 1
0 4
2 1
7 1
7 6
2 2
```
### 样例输出 #1
```
13
```传送门
一道非常简单的树形dp,此题一看就会让人联想到树形dp,但是唯一麻烦的就是没有直接选修课的数量有点多怎么半,那就有好多颗树了,这里其实我们可以将他们合并起来,全部都变成一棵树上的东西,选取的课的数目加1,然后这题就要多简单就有多简单了,简直不要太板子题
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef double D;
const int N = 3e3 + 10;
typedef pair<int, int> Pii;
vector<int> e[N];
vector<Pii>zhu;
vector<int>fu;
int f[N][N];
int qu[N];
int n, m;
void dfs(int u,int fa){
f[u][1]=qu[u];
for(auto tt:e[u]){
int son=tt;
dfs(son,u);
for(int j=m;j>0;j--){
for(int k=1;k<=j;k++){
f[u][j]=max(f[u][j],f[u][k]+f[son][j-k]);
}
}
}
}
void solved()
{
cin >> n >> m;
m++;
qu[0]=0;
for (int i = 1; i <= n; i++)
{
int k,s;
cin>>k>>s;
qu[i]=s;
e[k].push_back(i);
}
dfs(0,-1);
cout<<f[0][m]<<"\n";
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
t = 1;
while (t--)
{
solved();
}
return 0;
}
快去试试吧!!!