ZOJ3201 Tree of Tree(树形DP)

题目大概求一棵树中大小为k的子树的最大权和。

dp[u][k]表示以u为根的子树中包含u结点的大小为k的子树的最大权和,然后树上背包转移转移很容易。。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 #define MAXN 111
 6 
 7 struct Edge{
 8     int v,next;
 9 }edge[MAXN<<1];
10 int NE,head[MAXN];
11 void addEdge(int u,int v){
12     edge[NE].v=v; edge[NE].next=head[u];
13     head[u]=NE++;
14 }
15 
16 int n,k,val[MAXN],d[MAXN][MAXN];
17 void dp(int u,int fa){
18     d[u][0]=0; d[u][1]=val[u];
19     for(int i=head[u]; i!=-1; i=edge[i].next){
20         int v=edge[i].v;
21         if(v==fa) continue;
22         dp(v,u);
23         for(int a=k; a>=2; --a){
24             for(int b=0; b<a; ++b){
25                 if(d[u][a-b]==-1 || d[v][b]==-1) continue;
26                 d[u][a]=max(d[u][a],d[u][a-b]+d[v][b]);
27             }
28         }
29     }
30 }
31 
32 int main(){
33     int a,b;
34     while(~scanf("%d%d",&n,&k)){
35         for(int i=0; i<n; ++i){
36             scanf("%d",val+i);
37         }
38         NE=0;
39         memset(head,-1,sizeof(head));
40         for(int i=1; i<n; ++i){
41             scanf("%d%d",&a,&b);
42             addEdge(a,b);
43             addEdge(b,a);
44         }
45         memset(d,-1,sizeof(d));
46         dp(0,0);
47         int res=-1;
48         for(int i=0; i<n; ++i){
49             res=max(res,d[i][k]);
50         }
51         printf("%d
",res);
52     }
53     return 0;
54 }
原文地址:https://www.cnblogs.com/WABoss/p/5502766.html