考虑构建网络流模型。
对于每条树边,由祖先向儿子连一条容量为di,费用为0的边。对于每条覆盖路径,由深度小的向深度大的连一条容量为1,费用为ci的边。跑一边最大费用循环流即可。
最大费用循环流基本思路:
1.建网络流那样有反向弧的图;
2.用spfa最长路在残量网络找正环(最好用dfs找),如果一个点在一次dfs中再次出现,则找到了一个环,把它流满。
3.知道找不到正环为止。
代码
type
edge=^edgenode;
edgenode=record
t,c,f,w:longint;
next,rev:edge;
end;
var
ca,tt,i,n,m,x,y,z:longint;
ans:int64;
con:array[0..10100]of edge;
deep:array[0..10100]of longint;
visit:array[0..10100]of boolean;
lj:array[0..10100]of edge;
dist:array[0..10100]of int64;
const maxl=1000000000000000;
procedure ins(x,y,c,w,b:longint);
var
p:edge;
begin
new(p);
p^.t:=y;
p^.c:=c;
p^.f:=0;
p^.w:=w;
p^.next:=con[x];
con[x]:=p;
new(p);
p^.t:=x;
p^.f:=0;
if b=1 then begin p^.c:=0; p^.w:=-w; end
else begin p^.c:=c; p^.w:=w; end;
p^.next:=con[y];
con[y]:=p;
con[x]^.rev:=con[y];
con[y]^.rev:=con[x];
end;
procedure init;
var
i:longint;
p:edge;
begin
for i:=1 to n do
begin
p:=con[i];
while p<>nil do
begin
if deep[i]>deep[p^.t] then begin p^.c:=0; p^.w:=-p^.w end;
p:=p^.next;
end;
end;
end;
procedure dfs(v,fa:longint);
var
p:edge;
begin
p:=con[v];
deep[v]:=deep[fa]+1;
while p<>nil do
begin
if p^.t<>fa then dfs(p^.t,v);
p:=p^.next;
end;
end;
function dfs2(v:longint):boolean;
var
p,q:edge;
cost:longint;
begin
dfs2:=false;
visit[v]:=true;
p:=con[v];
while p<>nil do
begin
if (p^.c>p^.f)and(dist[p^.t]<dist[v]+p^.w) then
begin
dist[p^.t]:=dist[v]+p^.w;
lj[p^.t]:=p;
if visit[p^.t]=false then dfs2:=dfs2(p^.t)
else
begin
q:=p;
cost:=0;
repeat
q^.f:=q^.f+1;
q^.rev^.f:=q^.rev^.f-1;
q:=lj[q^.rev^.t];
cost:=cost+q^.w;
until q=p;
ans:=ans+cost;
exit(true);
end;
end;
if dfs2=true then exit(true);
p:=p^.next;
end;
visit[v]:=false;
end;
procedure maxflow;
var
i:longint;
begin
repeat
fillchar(visit,sizeof(visit),0);
dist[1]:=0;
for i:=2 to n do
dist[i]:=-maxl;
for i:=1 to n do
lj[i]:=nil;
until dfs2(1)=false;
end;
begin
readln(ca);
for tt:=1 to ca do
begin
for i:=1 to n do
con[i]:=nil;
readln(n,m);
for i:=1 to n-1 do
begin
readln(x,y,z);
ins(x,y,z,0,0);
end;
dfs(1,0);
init;
for i:=1 to m do
begin
readln(x,y,z);
if deep[x]<deep[y] then ins(y,x,1,z,1)
else ins(x,y,1,z,1);
end;
ans:=0;
maxflow;
writeln(ans);
end;
end.