题意:
现在有 N门功课,每门课有个学分,每门课有一门或没有直接先修课(若课程a是课程b的先修课即只有学完了课程a,才能学习课程b)。
一个学生要从这些课程里选择 M 门课程学习,问他能获得的最大学分是多少
思路:
样例:
7 4 2 2 0 1 0 4 2 1 7 1 7 6 2 2
答案
13
第二行开始v,w,第i+1行v和i连接,i点点值是w,如果是v==0,就是不需要任何直接先修课
所以将他们看出以0的根的树,进行从底往高的处理dp,dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]);
初始值是dp[i][1]=w[i],因为虚构了一个0的科目,所以选课数量+1,就当作0这么科目必须修,但他的学分是0
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define il inline 5 #define it register int 6 #define inf 0x3f3f3f3f 7 #define lowbit(x) (x)&(-x) 8 #define mem(a,b) memset(a,b,sizeof(a)) 9 #define mod 1000000007 10 const int maxn=310; 11 struct node{ 12 int to,next; 13 }a[maxn<<1]; 14 int n,s,K,cnt,tot,head[maxn],w[maxn]; 15 int dp[maxn][maxn],sz[maxn]; 16 il void add(int u,int v){ 17 a[tot].next=head[u]; 18 a[tot].to=v;head[u]=tot++; 19 } 20 void dfs(int u,int fa){ 21 dp[u][1]=w[u];sz[u]=1; 22 for(it i=head[u];i!=-1;i=a[i].next){ 23 it v=a[i].to;if(v==fa){continue;} 24 dfs(v,u); 25 sz[u]+=sz[v]; 26 } 27 for(it i=head[u];i!=-1;i=a[i].next){ 28 it v=a[i].to;if(v==fa){continue;} 29 for(it j=K;j>=1;j--){ 30 for(it k=1;k<min(j,sz[u]);k++){ 31 dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]); 32 } 33 } 34 } 35 } 36 int main(){ 37 mem(head,-1);tot=0; 38 scanf("%d%d",&n,&K);K++;w[0]=0; 39 for(it i=1;i<=n;i++){ 40 int v; 41 scanf("%d%d",&v,&w[i]); 42 add(i,v);add(v,i); 43 } 44 dfs(0,-1); 45 printf("%d\n",dp[0][K]); 46 return 0; 47 }
这题一开始没想到以0为根的树,所以我把所有的树进行了分开算,代码量是真的大,然后写得一塌糊涂,然后看了一眼题解,然后就重写了就过了