洛谷P2014 选课 求树取k个点的最大值

题意:

现在有 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 }
View Code

这题一开始没想到以0为根的树,所以我把所有的树进行了分开算,代码量是真的大,然后写得一塌糊涂,然后看了一眼题解,然后就重写了就过了

猜你喜欢

转载自www.cnblogs.com/luoyugongxi/p/12285515.html
今日推荐