将功补过 树形动态规划
题目大意
对于一个二叉树,除根节点外,每个节点都有相应的一个权值。在此基础上,求保留多少个点使得其仍然满足树的性质且权值总和最大。
分析
具体方法见:http://blog.csdn.net/a_loud_name/article/details/51326123
代码
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,nm: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,nm); 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); if nm<=f[1,m] then writeln('TRUE') else writeln('FALSE'); writeln(f[1,m]-nm); end.