不解释的MST,把已经有道路的两个村庄之间建一条长度为0的边,然后Kruskal。我开始是把已经有路的村庄合并,WA了
p.s.这个题的Discuss里面楼要倒了……
Var
a,b,e,f:array[1..100000]of longint;
n,m,sum,ans:longint;
Procedure addgraph(x,y,z:longint);
begin
inc(m);
a[m]:=x;b[m]:=y;e[m]:=z;
end;
Procedure init;
var
i,j,pre,k:longint;
begin
readln(n);
fillchar(f,sizeof(f),0);
for i:=1 to n do
begin
for j:=1 to n do
begin
read(pre);
addgraph(i,j,pre);
end;
readln;
end;
readln(k);
for i:=1 to k do
begin
read(j,pre);
addgraph(j,pre,0);
end;
end;
Procedure qsort(l,r:longint);
var
i,j,x,y:longint;
begin
i:=l;j:=r;x:=e[(l+r)shr 1];
Repeat
while e[i]<x do inc(i);
while e[j]>x do dec(j);
if i<=j then
begin
y:=a[i];a[i]:=a[j];a[j]:=y;
y:=b[i];b[i]:=b[j];b[j]:=y;
y:=e[i];e[i]:=e[j];e[j]:=y;
inc(i);dec(j);
end;
Until i>j;
if i<r then qsort(i,r);
if l<j then qsort(l,j);
end;
Function find(x:longint):longint;
var
k:longint;
begin
k:=x;
while f[k]<>0 do k:=f[k];
find:=k;
end;
Procedure kruskal;
var
i,j,p,q:longint;
begin
qsort(1,m);
for i:=1 to m do
begin
p:=find(a[i]);
q:=find(b[i]);
if p<>q then
begin
f[q]:=p;
inc(sum,e[i]);
inc(ans);
end;
if ans>=n-1 then break;
end;
writeln(sum);
end;
Begin
init;
kruskal;
End.