内容目录
这题告诉我一个道理:数组开得太小会出现Time Limit Exceeded
言归正传:这题的DP方程是f[x,i]:=w[i]+∑(best[y],f[y,i]-w[i]) //f[x,i]指 x 的供应站为 i 时,x子树全取的最小代价
best[y]表示min(best[y,i]) 预处理
y为x的儿子
如果x的子树有重叠的供应站,那么这个供应站只能是x的供应站i
多叉树可以用边表存的(难道树形DP=DFS?)
《一张一弛,解题之道——“约制、放宽”方法在解题中的应用》
http://www.doc88.com/p-670874250550.html
Program p2152; var t,n,i,j,u,v,w2,tot,root,father:longint; d,w,best,dis:array[1..2000] of longint; head,tail,edge,we:array[1..2000] of longint; f:array[1..1000,1..1000] of longint; function min(a,b:longint):longint; begin if a<b then exit(a) else exit(b); end; procedure addedge(u,v,w:longint); var i,j:longint; begin inc(tot); we[tot]:=w; edge[tot]:=v; tail[tot]:=head[u]; head[u]:=tot; end; procedure calcdis(x:longint); var i,p:longint; begin p:=head[x]; while (p<>0) do begin if (dis[edge[p]]=-1) then begin dis[edge[p]]:=dis[x]+we[p]; calcdis(edge[p]); end; p:=tail[p]; end; end; procedure dfs(x,fa:longint); var i,j,p:longint; begin best[x]:=maxlongint; p:=head[x]; while (p<>0) do begin if (edge[p]<>fa) then dfs(edge[p],x); p:=tail[p]; end; for i:=1 to n do dis[i]:=-1; dis[x]:=0; calcdis(x); for i:=1 to n do begin if (dis[i]>d[x]) then f[x,i]:=maxlongint else begin f[x,i]:=w[i]; p:=head[x]; while (p<>0) do begin if (edge[p]<>fa) then inc(f[x,i],min(best[edge[p]],f[edge[p],i]-w[i])); p:=tail[p]; end; best[x]:=min(best[x],f[x,i]); end; end; end; begin read(t); while t>0 do begin tot:=0; fillchar(head,sizeof(head),0); fillchar(tail,sizeof(tail),0); read(n); for i:=1 to n do read(w[i]); for i:=1 to n do read(d[i]); for i:=1 to n-1 do begin read(u,v,w2); addedge(u,v,w2); addedge(v,u,w2); end; root:=1; dfs(1,-1); writeln(best[root]); dec(t); end; end.