poj 3013 Big Christmas Tree spfa
题目大意
要建一棵圣诞树,使得总的花费最小。具体规则是:圣诞树是一颗无向树形图,其中,编号为1的节点为根节点,原始图中每条边具有边权,每个点也有一值权。圣诞树中,各条边的花费是该边权*该边的子树中所有点值,总的花费则是圣诞树中所有边的花费之和。
分析
1.对点u,只有从点u到根结点之间的边会乘以点u的重量。
2.所以,对于点u;最小的花费是要使点u到根结点的边权最小,即最短路。
3.所以,圣诞树的最小总花费=每条边权*该边的子树中所有点值
=每个点值*该点到根结点的最短路
注意
如果有的点无法到达,就要输出‘No Answer’
如果输入的边数或点数为0,输出0(我wa了好多次)
一定要注意范围,要用int64
代码
const maxe=100000; maxv=2000000; type arr=record x,y,w,next:int64; end; var n,m,s,q,nm:longint; ls:array[0..maxe] of longint; a:array[0..maxv] of arr; f:array[0..maxe] of int64; v:array[0..maxe] of int64; d,b:array[0..maxe] of int64; i,j,k,ll:longint; ans,max:int64; procedure spfa; var i,j,k:longint; head,tail:longint; begin fillchar(f,sizeof(f),63); max:=f[1]; head:=0; tail:=1; v[1]:=1; d[1]:=1; f[1]:=0; repeat head:=head+1; j:=ls[d[head]]; while j<>0 do begin with a[j] do begin if f[x]+w<f[y] then begin f[y]:=f[x]+w; if v[y]=0 then begin tail:=tail+1; d[tail]:=y; v[y]:=1; end; end; j:=next; end; end; v[d[head]]:=0; until head=tail; end; begin readln(nm); for ll:=1 to nm do begin fillchar(ls,sizeof(ls),0); fillchar(d,sizeof(d),0); fillchar(b,sizeof(b),0); fillchar(a,sizeof(a),0); fillchar(v,sizeof(v),0); readln(n,m); for i:=1 to n do read(b[i]); for i:=1 to m do begin with a[i*2-1] do begin readln(x,y,w); next:=ls[x]; ls[x]:=i*2-1; end; a[i*2].x:=a[i*2-1].y; a[i*2].y:=a[i*2-1].x; a[i*2].w:=a[i*2-1].w; a[i*2].next:=ls[a[i*2].x]; ls[a[i*2].x]:=i*2; end; m:=m*2; spfa; ans:=0; for i:=1 to n do if f[i]=max then break else ans:=f[i]*b[i]+ans; if (f[i]=max) then writeln('No Answer') else writeln(ans); end; end.