树形dp(……)

# [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;
}

快去试试吧!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值