最小生成树kruskal算法

本文介绍了最小生成树的概念,重点阐述了Kruskal算法的原理,利用贪心策略和并查集数据结构来判断边是否构成回路,给出了代码实现,以及图的储存结构在算法中的应用。
摘要由CSDN通过智能技术生成

前言

最小生成树是什么?

一张连通图G的一个极大无环子图就是连通图G的生成树,通俗来讲就是从图中找出一棵树包含全部的点,一个图不只一棵生成树,其中权值最小的那若干棵树就是最小> 生成树


如何构建最小生成树

kruskal法

思路:贪心,每次都看最小的边合不合适。

  1. 从图中取出权值最小的边
  2. 判断边是否构成回路
    • 构成回路,舍弃
    • 不构成回路,成为树的一条边
  3. 重复1,2步骤,直至树中有n-1条边

代码实现

并查集

用于判断某条边是否与已有的边集构成回路,对某条边a->b,若a,b都是树中的点则边ab会与树构成回路

//并查集
const int M=1e5+10;
int fa[M];

//路径压缩
int find(int a){
    //return fa[a]<0?a:find(fa[a]);
    int r;
    for(r=a;fa[r]>0;r=fa[r]);
    while(a!=r){
        int tmp=fa[a];
        fa[a]=r;
        a=tmp;
    }
    return a;
}

//加权合并
void merge(int a,int b){
    int ia=find(a),ib=find(b);
    if(ia==ib){
        return;
    }
    //
    if(ia<=ib){
        fa[ia]+=fa[ib];
        fa[ib]=ia;
    }else{
        fa[ib]+=fa[ia];
        fa[ia]=ib;
    }
}

图储存结构

const int N=1e5+10;
struct Edge{
    int start,end;
    int w;
}graph[N];

kruskal算法

//重载小于号使用优先队列构建小顶堆,选取权值最小的边
bool operator<(const Edge &a,const Edge &b){
    return a.w>b.w;
}

void kruskal(){
    memset(fa,-1,sizeof(fa));
    //构建小顶堆
    priority_queue<Edge> pq;
    cin>>n>>m;
    Edge tmp;
    for(int i=0;i<m;i++){
        cin>>tmp.start>>tmp.end>>tmp.w;
        pq.push(tmp);
    }
    int cnt=1;
    while(!pq.empty()&&cnt<n){
        tmp=pq.top(),pq.pop();
        if(find(tmp.start)==find(tmp.end)){
            continue;
        }
        merge(tmp.start,tmp.end);
        cout<<tmp.start<<" "<<tmp.end<<endl;
        cnt++;
    }
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值