[描述]:
在一个初始化为空的无向图中,不断加入新边。如果当前图连通,就求出当前图最小生成树的总权值;否则,输出-1。
[分析]:
通过并查集判断连通性,若当前边的两端点已连通,则在这条环上找最大的一条边删去。
[代码]:
program maintain;
var
father:array[1..200] of longint;
g:array[1..200,1..200] of longint;
N,M,Len_count,Cost,i,S,T,L:longint;
q:array[0..200] of longint; top,last:longint;
pre:array[1..200] of longint;
v:array[1..200] of boolean;
function f(x:longint):longint;
begin
if father[x]=0 then exit(x)
else begin
father[x]:=f(father[x]);
exit(father[x]);
end;
end;
procedure Sift(S,T,L:longint);
var
Max,SS,TT,i,j:longint;
begin
fillchar(v,sizeof(v),false);
top:=0; last:=1; q[1]:=S; v[s]:=true;
while (top<last)and(not v[T]) do begin
inc(top);
i:=q[top];
for j:=1 to N do
if (not v[j])and(g[i,j]>0) then begin
v[j]:=true;
pre[j]:=i;
inc(last);
q[last]:=j;
end;
end;
i:=T; Max:=0;
while i<>S do begin
if g[pre[i],i]>Max then begin
Max:=g[pre[i],i];
SS:=pre[i];
TT:=i;
end;
i:=pre[i];
end;
if Max>L then begin
g[SS,TT]:=0;
g[TT,SS]:=0;
g[S,T]:=L;
g[T,S]:=L;
dec(Cost,Max);
inc(Cost,L);
end;
end;
begin
assign(input,'maintain.in');
assign(output,'maintain.out');
reset(input);
rewrite(output);
fillchar(father,sizeof(father),0);
fillchar(g,sizeof(g),0);
Len_count:=0;
Cost:=0;
readln(N,M);
for i:=1 to M do begin
readln(S,T,L);
if f(S)<>f(T) then begin
father[f(S)]:=f(T);
g[S,T]:=L;
g[T,S]:=L;
inc(Len_count);
inc(Cost,L);
end else Sift(S,T,L);
if Len_count=N-1 then
writeln(Cost)
else writeln(-1);
{
Writeln(#32#32#32,'Debug:');
Writeln(#32#32#32,'LenCount:',Len_count);
for j:=1 to N-1 do
for k:=j+1 to N do
if g[j,k]<>0 then
Writeln(#32#32#32,'g[',j,',',k,']:=',g[j,k]);
}
end;
close(input);
close(output);
end.