【模板】Kruskal算法求最小生成树

克鲁斯卡尔算法是一种求最小生成树的方法,通过按代价排序边并逐步连接不同树的顶点来构建。文章介绍了算法原理,提供了模板实现,并通过例题进行解析。
摘要由CSDN通过智能技术生成



1.Kruskal算法介绍

克鲁斯卡尔算法可以称为“加边法”,初始最小生成树边数为0,每迭代一次就选择一条满足条件的最小代价边,加入到最小生成树的边集合里。

  1. 把图中的所有边按代价从小到大排序;
  2. 把图中的n个顶点看成独立的n棵树组成的森林;
  3. 按权值从小到大选择边,所选的边连接的两个顶点ui,viui,vi,应属于两颗不同的树,则成为最小生成树的一条边,并将这两颗树合并作为一颗树。
  4. 重复(3),直到所有顶点都在一颗树内或者有n-1条边为止。
    在这里插入图片描述

总结:从小开始加,确保无回路(树)



|| 区别普利姆最小生成树算法:普利姆算法从顶点的角度为出发点。时间复杂度为O(n^2)。**更适合于稠密度更高的连通网**。 而克鲁斯卡尔算法从边的角度求最小生成树,时间复杂度为O(eloge),**更适合于稠密度更高的连通网**。
|| 判断是否会产生回路的方法为: 在初始状态下给每个顶点赋予不同的标记,对于遍历过程的每条边,其都有两个顶点,判断这两个顶点的标记是否一致,如果一致,说明它们本身就处在一棵树中,如果继续连接就会产生回路;如果不一致,说明它们之间还没有任何关系,可以连接。

2.模板实现

//最小生成树(Kruskal算法)
#include<iostream>
#include<algorithm>
using namespace std;

struct point{
    int x;
    int y;
    int v;
}; //写结构体用来构造边 
point a[10000];//存边
 
int cmp(const point &a,const point &b){
    if(a.v<b.v) return 1;
    else return 0;
}//快排要用到的比较函数 ,从小到大
 
int fat[101];
int father(int x){
    if(fat[x]!=x) return fat[x]=father(fat[x]);
    else return fat[x];
}//找出一个点属于哪个集合(找这个点的爹) 

void unionn(int x,int y){
    int fa=father(x);
    int fb=father(y);
    if(fa!=fb) fat[fa]=fb;
}//将被边连接的两个独立集合合并 

int main(){
    int i,j,n,m,k=0,ans=0,cnt=0;
    cin>>n;
    for(i=1;i<=n;i++)
    for(j=1;j<=n;j++)
    {
        cin>>m;
        if(m!=0){
            k++;
            a[k].x=i;
            a[k].y=j;
            a[k].v=m;
        }
    }//输入,存边 
    sort(a+1,a+1+k,cmp);//快排所有边 
    
    for(i=1;i<=n;i++){
        fat[i]=i;
    }//初始化,将每个点看做独立集合 
    
    for(i=1;i<=k;i++){
        if(father(a[i].x)!=father(a[i].y)){//如果这条边连接的两个点属于不同集合 
            ans+=a[i].v;//将这条边加入最小生成树 
            unionn(a[i].x,a[i].y);//将两个点所在的集合合并为一个集合 
            cnt++;//计数已添加的边 
        }
        if(cnt==n-1) break;//当已经有n-1条边的时候,结束 
    }
    
    cout<<ans;
    return 0;
    
}

/




3.例题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
///解法
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值