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\n",res); 52 } 53 return 0; 54 }