题意:有一棵树,树上的每条边都有一个权值。现在从根节点开始遍历m条边,求最多能获得多少权值。
分析:很裸的树形dp。f[i,j]表示从节点i开始向下走j条边最多能获得多少权值。
f[i,j]=max(f[lson,j-1]+w[i,lson],f[rson,j-1]+w[i,rson],f[lson,k]+f[rson,j-k-2]+w[i,lson]+w[i,rson])
代码:
var n,m,p,x,y,z,i:longint; v:array[1..100] of boolean; l,r,d:array[1..100] of longint; f,a,b:array[1..100,0..100] of longint; function max(x,y:longint):longint; begin if x>y then exit(x) else exit(y); end; procedure dp(x:longint); var i,j:longint; begin if l[x]=0 then exit; dp(l[x]); dp(r[x]); for i:=1 to m do begin f[x,i]:=max(f[l[x],i-1]+d[l[x]],f[r[x],i-1]+d[r[x]]); for j:=0 to i-2 do f[x,i]:=max(f[x,i],f[l[x],j]+f[r[x],i-j-2]+d[l[x]]+d[r[x]]); end; end; procedure build(x:longint); var i:longint; begin v[x]:=false; for i:=1 to a[x,0] do if v[a[x,i]] then begin if l[x]=0 then l[x]:=a[x,i] else r[x]:=a[x,i]; d[a[x,i]]:=b[x,i]; build(a[x,i]); end; end; begin readln(n,m,p); fillchar(v,sizeof(v),true); for i:=1 to n-1 do begin readln(x,y,z); inc(a[x,0]); a[x,a[x,0]]:=y; b[x,a[x,0]]:=z; inc(a[y,0]); a[y,a[y,0]]:=x; b[y,a[y,0]]:=z; v[y]:=false; end; fillchar(v,sizeof(v),true); build(1); dp(1); if f[1,m]>=p then writeln('TRUE') else writeln('FALSE'); writeln(f[1,m]-p); end.