洛谷 P2015 二叉苹果树(树形dp)

传送门


解题思路

很显然的树形dp,设dp[i][j]表示在子树i上保留j条边的最大苹果树,从儿子节点转移过来即可,注意若某个儿子不选,则以此儿子为根的子树都不能选。

还有就是因为是二叉树,可以提前遍历一遍求出每个点的两个或零个儿子,就不用在求dp时倒序枚举了,算是一个小技巧趴。

AC代码

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cmath>
 4 #include<cstdio>
 5 #include<cstring>
 6 using namespace std;
 7 int n,q,cnt,p[105],dp[105][105],son[105][3];
 8 struct node{
 9     int v,value,next;
10 }e[205];
11 void insert(int u,int v,int value){
12     cnt++;
13     e[cnt].v=v;
14     e[cnt].value=value;
15     e[cnt].next=p[u];
16     p[u]=cnt;
17 } 
18 void dfs(int u,int fa){
19     for(int i=p[u];i!=-1;i=e[i].next){
20         int v=e[i].v;
21         if(v==fa) continue;
22         son[u][++son[u][0]]=i;
23         dfs(v,u);
24     }
25 }
26 void dfs2(int u){
27     if(son[u][0]==0) return;
28     int v1=e[son[u][1]].v;
29     int v2=e[son[u][2]].v;
30     dfs2(v1);
31     dfs2(v2);
32     for(int i=1;i<=q;i++){
33         dp[u][i]=max(dp[v1][i-1]+e[son[u][1]].value,dp[v2][i-1]+e[son[u][2]].value);
34         for(int j=0;j<=i-2;j++) dp[u][i]=max(dp[u][i],dp[v1][j]+dp[v2][i-2-j]+e[son[u][1]].value+e[son[u][2]].value);
35     }
36 }
37 int main()
38 {
39     memset(p,-1,sizeof(p));
40     cin>>n>>q;
41     for(int i=1;i<=n-1;i++){
42         int u,v,value;
43         cin>>u>>v>>value;
44         insert(u,v,value);
45         insert(v,u,value);
46     }
47     dfs(1,-1);
48     dfs2(1);
49     cout<<dp[1][q];
50     return 0;
51 }

 

posted @ 2020-10-19 23:51  尹昱钦  阅读(122)  评论(0编辑  收藏  举报