tyvj1307 kruskal+并查集 最小生成树

这题一开始没注意数据范围,RE了好几次。。

如果规定某些边一定要经过,用kruskal方便地先加入这些边;如果规定某些点一定经过,用prim更方便。

另外kruskal算法要用到并查集

program tt;
var n,m,i,a,b:longint;
    ans:int64;
    fa:array[1..2010]of longint;
    p,v,u,w:array[1..10000]of longint;
procedure qsort(x,y:longint);
var i,j,mid,t,mid1:longint;
begin
 i:=x;j:=y;
 mid:=p[(x+y) div 2];
 mid1:=w[(x+y) div 2];
 repeat
  while (p[i]<mid)or(p[i]=mid)and(w[i]<mid1) do i:=i+1;
  while (p[j]>mid)or(p[j]=mid)and(w[j]>mid1) do j:=j-1;
  if i<=j then
   begin
    t:=p[i];p[i]:=p[j];p[j]:=t;
    t:=u[i];u[i]:=u[j];u[j]:=t;
    t:=v[i];v[i]:=v[j];v[j]:=t;
    t:=w[i];w[i]:=w[j];w[j]:=t;
    i:=i+1;j:=j-1;
   end;
 until i>j;
 if i<y then qsort(i,y);
 if x<j then qsort(x,j);
end;
function find(x:longint):longint;
var i,t:longint;
begin
 i:=x;
 while fa[i]<>i do
  i:=fa[i];
 while fa[x]<>x do
  begin
   t:=x;
   x:=fa[x];
   fa[t]:=i;
  end;
 find:=i;
end;
begin
 read(n,m);
 for i:=1 to m do
  read(p[i],u[i],v[i],w[i]);
 qsort(1,m);
 for i:=1 to n do fa[i]:=i;
 for i:=1 to m do
  begin
   if p[i]=1 then
    begin
     ans:=ans+w[i];
     a:=find(u[i]);
     b:=find(v[i]);
     if a<>b then fa[a]:=b;
    end
   else
    begin
     a:=find(u[i]);
     b:=find(v[i]);
     if a<>b then
      begin
       ans:=ans+w[i];
       fa[a]:=b;
      end;
    end;
  end;
 write(ans);
end.


你可能感兴趣的:(最小生成树,图论,kruskal,noip)