Title Link: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=17662
Test instructions: A two-fork tree that has a right value for a side, and a node number of 1~n,1 is the root node. To cut off some edges, just keep the Q bar, the root node of the sub-tree formed by the Q-bar is 1, and the maximum weight of this subtree is sought.
Analysis: 1.dp[u][i] Represents a subtree that has a root node of u, preserving the maximum weight of I nodes. The weight of each edge is considered to be the weight of the son node in the connected two nodes. Then a total of m+1 nodes will be retained.
So there are: Dp[u][i]=max (dp[u][i],dp[v][k]+dp[u][i-k]+w). ans=dp[1][m+1].
2.dp[u][i] indicates that u is the subtree of the root node and retains the maximum weight of the i edges. The K-Bar is selected in the subtree with the U-point as the root node, so the son of U's node v represents at most k-1 bars in the subtree, because if you select an edge in the V subtree, the Berbish of U to v.
So there are: Dp[u][i]=max (dp[u][i],dp[u][i-k]+dp[v][k-1]+w). Ans=dp[1][m].
Code for Method 1:
#include <cstdio>#include<cstring>#include<cmath>#include<iostream>#include<algorithm>#include<queue>#include<cstdlib>#include<stack>#include<vector>#include<Set>#include<map>#defineLL Long Long#defineMoD 1000000007#defineINF 0x3f3f3f3f#defineN 110#defineCLR (a) (Memset (A,0,sizeof (a)))using namespacestd;structedge{intV,w,next; Edge () {} Edge (intVintWintnext): V (v), W (W), Next (next) {}}e[2*N];inthead[n],dp[n][n],num[n],tot,n,m;voidAddedge (intUintVintW) {E[tot]=Edge (V,w,head[u]); Head[u]=tot++;}voidDfsintUintFA) {Num[u]=1; for(intI=head[u];~i;i=E[i].next) { intv=e[i].v,w=E[I].W; if(V==FA)Continue; DFS (V,U); Num[u]+=Num[v]; for(intj=num[u];j>=1; j--) for(intk=1; k<j&&k<=num[v];k++)//notice here k<j. Because the subtree node u point is required, select up to j-1 in the subtree nodeDp[u][j]=max (dp[u][j],dp[u][j-k]+dp[v][k]+W); }}intMain () {intu,v,w; while(SCANF ("%d%d", &n,&m) >0) {memset (head,-1,sizeof(head)); CLR (DP); Tot=0; for(intI=1; i<n;i++) {scanf ("%d%d%d",&u,&v,&W); Addedge (U,V,W); Addedge (V,U,W); } DFS (1,-1); printf ("%d\n", dp[1][m+1]); }}
View Code
Code for Method 2:
#include <cstdio>#include<cstring>#include<cmath>#include<iostream>#include<algorithm>#include<queue>#include<cstdlib>#include<stack>#include<vector>#include<Set>#include<map>#defineLL Long Long#defineMoD 1000000007#defineINF 0x3f3f3f3f#defineN 110#defineCLR (a) (Memset (A,0,sizeof (a)))using namespacestd;structedge{intV,w,next; Edge () {} Edge (intVintWintnext): V (v), W (W), Next (next) {}}e[2*N];inthead[n],dp[n][n],tot,n,m;voidAddedge (intUintVintW) {E[tot]=Edge (V,w,head[u]); Head[u]=tot++;}voidDfsintUintFA) { for(intI=head[u];~i;i=E[i].next) { intv=e[i].v,w=E[I].W; if(V==FA)Continue; DFS (V,U); for(intj=m;j>=1; j--) for(intk=1; k<=j;k++) Dp[u][j]=max (dp[u][j],dp[u][j-k]+dp[v][k-1]+W); }}intMain () {intu,v,w; while(SCANF ("%d%d", &n,&m) >0) {memset (head,-1,sizeof(head)); CLR (DP); Tot=0; for(intI=1; i<n;i++) {scanf ("%d%d%d",&u,&v,&W); Addedge (U,V,W); Addedge (V,U,W); } DFS (1,-1); printf ("%d\n", dp[1][m]); }}
View Code
ural1018 (tree-shaped DP)