题意:给n个点从1到n标号,下面一行是每个点的权,另外给出m条边,下面是每条边的信息,两个端点+权值,边是无向边。你的任务是选出一些边,使这个图变成一棵树。这棵树的花费是这样算的,1号固定为树根,树中每个双亲节点下面的边都有个单价(即边权),然后单价乘上这条边的下面所有的子孙后代的点权和。
分析:每个点的权都要乘上好几条边的权,就是这个点回到点1的路径上的那些边。要想最小,就是求到到1点的最短路。点数有可能是0。
spfa!!!
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.