题目大意
要建一棵圣诞树,使得总的花费最小。具体规则是:圣诞树是一颗无向树形图,其中,编号为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.