题目
https://jzoj.net/junior/#main/show/1661
小结
树形dp,和普通dp没什么区别,只是在树上做而已。
首先这题,我们设f[i,j]表示更新到第i个点时,下面取j条边。然后就可以乱搞啦~~
每次枚举当前的条数和子节点的条数,记得倒过来更新,这样才可以累加。很像背包有木有~~
所以f[i,j]=max(f[i,j],f[x,j-l]+f[y,l-1]+len[i,y]);//y是子节点。
就过啦~~~
var
n,q,i,j,tot,x,y,z:longint;
f,a:array[0..1000,0..1000]of longint;
g:array[0..1000]of longint;
tov,last,next:array[0..1000]of longint;
bz:array[0..1000]of boolean;
procedure insert(x,y,z:longint);
begin
inc(tot);
tov[tot]:=y;
a[x,y]:=z;
next[tot]:=last[x];
last[x]:=tot;
end;
function min(a,b:longint):longint;
begin
if a>b then exit(b);
exit(a);
end;
function max(a,b:longint):longint;
begin
if a<b then exit(b);
exit(a);
end;
procedure dg(x:longint);
var
i,j,y,k,l:longint;
begin
bz[x]:=true;
i:=last[x];
while i<>0 do
begin
y:=tov[i];
if bz[y]=false then
begin
dg(y);
g[x]:=g[x]+g[y]+1;
for j:=min(g[x],q) downto 1 do//当前的状态
for l:=min(g[x],j) downto 1 do//上次的状态
f[x,j]:=max(f[x,j],f[x,j-l]+f[y,l-1]+a[x,y]);
end;
i:=next[i];
end;
end;
begin
readln(n,q);
for i:=1 to n-1 do
begin
readln(x,y,z);
insert(x,y,z);
insert(y,x,z);
end;
dg(1);
writeln(f[1,q]);
end.