洛谷 P3366 【模板】最小生成树

本文介绍了一道关于求解最小生成树的经典算法题,通过使用并查集与Kruskal算法,解决了一个无向图中寻找最小生成树的问题,并提供了完整的实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出orz

输入输出格式

输入格式:
第一行包含两个整数N、M,表示该图共有N个结点和M条无向边。(N<=5000,M<=200000)

接下来M行每行包含三个整数Xi、Yi、Zi,表示有一条长度为Zi的无向边连接结点Xi、Yi

输出格式:
输出包含一个数,即最小生成树的各边的长度之和;如果该图不连通则输出orz

输入输出样例

输入样例#1:
4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3
输出样例#1:
7
说明

时空限制:1000ms,128M

数据规模:

对于20%的数据:N<=5,M<=20

对于40%的数据:N<=50,M<=2500

对于70%的数据:N<=500,M<=10000

对于100%的数据:N<=5000,M<=200000

这里写图片描述

所以最小生成树的总边权为2+2+3=7

分析:最小生成树模版题。
(并查集+排序+Kruskal算法)

代码:

var
 p,r:array [1..10001] of longint;
 a:array [1..200001,1..3] of longint;
 n,m,p1,u,v,w,ans,k,i:longint;
function find(x:longint):longint;
 var y,root,w:longint;
 begin
 y:=x;
   while p[y]>0 do
    y:=p[y];
   root:=y;
   y:=x;
   while p[y]>0 do
    begin
     w:=p[y];
     p[y]:=root;
     y:=w;
    end;
   find:=root;
 end;

procedure union(x,y:longint);
 var
  u,v:longint;
begin
 u:=find(x);
 v:=find(y);
 if u=v then exit;
 if r[u]<=r[v] then
  begin
   p[u]:=v;
   if r[u]=r[v] then inc(r[v]);
  end
 else p[v]:=u;
end;

procedure qsort(l,r:longint);
  var
    i,j,key,temp:longint;
  begin
    if l>=r then exit;
    i:=l;j:=r;
    key:=a[l+random(r-l+1),3];
    repeat
      while  (a[i,3]<key) do inc(i);
      while  (a[j,3]>key) do dec(j);
      if i<=j then
      begin
        temp:=a[i,1];a[i,1]:=a[j,1];a[j,1]:=temp;
        temp:=a[i,2];a[i,2]:=a[j,2];a[j,2]:=temp;
        temp:=a[i,3];a[i,3]:=a[j,3];a[j,3]:=temp;
        inc(i);dec(j);
      end;
    until i>j;
    qsort(l,j);
    qsort(i,r);
  end;


begin
 readln(n,m);
 for i:=1 to m do
  begin
   readln(u,v,w);
   inc(k);
   a[k,1]:=u;
   a[k,2]:=v;
   a[k,3]:=w;
  end;
 qsort(1,k);
 for i:=1 to k do
  begin
   if find(a[i,1])<>find(a[i,2]) then
    begin
     union(a[i,1],a[i,2]);
     ans:=ans+a[i,3];
    end;
  end;
 write(ans);
end.
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值