二*苹果树 树型动态规划
题目大意
对于一个二叉树,除根节点外,每个节点都有相应的一个权值。在此基础上,求保留多少个点使得其仍然满足树的性质且权值总和最大。
分析
先建树。
ch[v,1],ch[v,2]分别存V节点的左右孩子。dp[v,l]存以V为根的树保留L个节点的最大权和。Num[v]为点v的权值。
dp[v,l]=max{dp[ch[v,1],j]+dp[ch[v,2],l-j-1]+num[v]} (0<=j<=l-1)
这里特别指出,为了使其仍然为二叉树,我们一定要保留根节点,因此j<=l-1。
然后,可以减枝。
然后2,注意边界:
如果l=0,那么dp[v,l]=0。
如果点v没有孩子,那么dp[v,l]=v的权值。
然后3,因为输入的是要保留m条边,而转化后的题目是保留nm个点,所以输入的m要加1.
代码
var f:array[0..200,0..200] of longint; a:array[0..200,1..3] of longint; b:array[0..200,0..200] of longint; v,num:array[0..200] of longint; i,j,k,l:longint; n,m:longint; ans:longint; procedure make(v:longint); var i,j,k:longint; begin for i:=1 to n do begin if b[v,i]>0 then begin a[v,1]:=i; num[i]:=b[v,i]-1; b[v,i]:=-1; b[i,v]:=-1; make(i); break; end; end; for i:=1 to n do begin if b[v,i]>0 then begin a[v,2]:=i; num[i]:=b[v,i]-1; b[v,i]:=-1; b[i,v]:=-1; make(i); break; end; end; end; procedure dfs(r,l:longint); var i,j,k:longint; begin if f[r,l]<>0 then exit; if l=0 then begin f[r,l]:=0; exit; end; if (a[r,1]=0) and (a[r,2]=0) then begin f[r,l]:=num[r]; exit; end; for i:=0 to l-1 do begin dfs(a[r,1],i); dfs(a[r,2],l-i-1); if f[r,l]<f[a[r,1],i]+f[a[r,2],l-i-1]+num[r] then f[r,l]:=f[a[r,1],i]+f[a[r,2],l-i-1]+num[r]; end; end; begin readln(n,m); m:=m+1; for i:=1 to n-1 do begin readln(j,k,l); b[j,k]:=l+1; b[k,j]:=l+1; end; fillchar(f,sizeof(f),0); fillchar(v,sizeof(v),0); fillchar(a,sizeof(a),0); v[0]:=1; make(1); dfs(1,m); writeln(f[1,m]); end.