usaco 3.1 agrinet 2008.7.16

usaco 3.1 agrinet 2008.7.16

{

ID:  

PROG: agrinet

LANG: PASCAL

}

 

program pppp;
const
 maxn=100;
 maxe=maxn*maxn;
type
 edge=record
        a,b    :longint;      //边的2个顶点
        len    :longint;      //边的长度
      end;
var
 edges :array[0..maxe]of edge;   //保存所有边的信息
 p,r   :array[0..maxn]oflongint;   //p[i]保存i的父亲节点,r用来实现Union-Find的rank启发式
 n,e,j,xs   :longint;     //n为顶点数,e为边数
  f1,f2:text;
  map:array[1..maxn,1..maxn]of 0..1;
procedure swap(a,b:longint);    //交换
begin
 edges[0]:=edges[a];
 edges[a]:=edges[b];
 edges[b]:=edges[0];
end;
 
procedure quicksort(l,r:longint);   //快速排序
var
 x,i,j :longint;
begin
 x:=edges[random(r-l+1)+l].len;
 i:=l;j:=r;
 
 repeat
   while edges[i].len<x do inc(i);
   while edges[j].len>x do dec(j);
   if i<=j then
     begin
       swap(i,j);
       inc(i);dec(j);
     end
 until i>j;
 
  ifl<j then quicksort(l,j);
  ifi<r then quicksort(i,r);
end;
 
procedure init;
var
 i     :longint;
begin
 assign(f1,'agrinet.in');reset(f1);
 assign(f2,'agrinet.out');rewrite(f2);
 readln(f1,n);e:=0;
 fillchar(map,sizeof(map),0);
  fori:=1 to n do
   for j:=1 to n do
     begin
        read(f1,xs);
               if(xs<>0)and(map[i,j]=0)and(map[j,i]=0) then
                  begin inc(e);
                     edges[e].a:=i;edges[e].b:=j;edges[e].len:=xs;
                      map[i,j]:=1;map[j,i]:=1;
                  end;
     end;
  fori:=1 to n do p[i]:=i;   //初始化并查集
 randomize;
 quicksort(1,e);      //使用快速排序将边按权值从小到大排列
end;
 
function find(x:integer):longint;     //并查集的Find,用来判断2个顶点是否属于一个连通分量
begin
  ifx<>p[x] then p[x]:=find(p[x]);
 find:=p[x]
end;
 
procedure union(a,b:longint);     //如果不属于且权值最小则将2个顶点合并到一个连通分量
var
 t     :integer;
begin
 a:=find(a);b:=find(b);
  ifr[a]>r[b] then begin t:=a;a:=b;b:=t end;
  ifr[a]=r[b] then inc(r[b]);
 p[a]:=b;
end;
 
procedure kruskal;      //主过程
var
 en    :longint;   //en为当前边的编号
 count :longint;   //统计进行了几次合并。n-1次合并后就得到最小生成树
 tot   :longint;   //统计最小生成树的边权总和
begin
 count:=0;en:=0; tot:=0;
 while count<n-1 do
   begin
     inc(en);
     with edges[en] do
       begin
         if find(a)<>find(b) then
           begin
              union(a,b);
              inc(tot,len);
              inc(count);
           end;
       end;
   end;
 writeln(f2,tot)
end;
 
{===========main==========}
begin
 init;
 kruskal;
 close(f1);close(f2);
end.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值