选课
题目描述
在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习。现在有N门功课,每门课有个学分,每门课有一门或没有直接先修课(若课程a是课程b的先修课即只有学完了课程a,才能学习课程b)。一个学生要从这些课程里选择M门课程学习,问他能获得的最大学分是多少?
输入输出格式
输入格式:第一行有两个整数N,M用空格隔开。(1<=N<=300,1<=M<=300)
接下来的N行,第I+1行包含两个整数ki和si, ki表示第I门课的直接先修课,si表示第I门课的学分。若ki=0表示没有直接先修课(1<=ki<=N, 1<=si<=20)。
输出格式:只有一行,选M门课程的最大得分。
输入输出样例
code:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n,m,f[2005][2005];
int head[2005],next[2005],w[2005];
int dfs(int x){
if (head[x]==-1) return 0;
int sum=0;
for (int i=head[x];i!=-1;i=next[i]){
int t=dfs(i);
sum+=t+1;
//01背包
for (int j=sum;j>=0;j--){
for (int k=0;k<=t;k++)
if (j-k-1>=0) f[x][j]=max(f[x][j],f[x][j-k-1]+f[i][k]);
}
}
return sum;
}
int main(){
scanf("%d%d",&n,&m);
memset(head,-1,sizeof(head));
for (int i=1;i<=n;i++){
int a;
scanf("%d%d",&a,&w[i]);
next[i]=head[a];
head[a]=i;
}
for (int i=1;i<=n;i++) f[i][0]=w[i];
f[0][0]=0;
dfs(0);
printf("%d",f[0][m]);
return 0;
建图的对比
void xx(int x,int y)
{
d[++w].nxt=h[x];
d[w].to=y;
h[x]=w;
}