图.kruskal算法(最小生成树)

  • 算法思想

1.令初始状态有n个顶点而无边的非连通图 ,图中每个顶点自成一个连通分量。
2.在边集表中选择代价最小的边。
3.用Find函数(代码中有注释)查找若该边依附的顶点,若落在中不同的连通图上,则将此边相连,合成一个新的连通图,否则舍去此边。
重复2,3操作,直到把所有的点连到一起为止
值得注意的是,构成最小生成树的边是n-1个,因此,可以对添边操作进行计数,循环n-1次即可停止循环。

  • 图示
    补充说明
    1.初始化图中六个小镇为独立的六个连通分量。
    2.依次连接权制为3,4,4的边
    3.直到找到权制为5的边时,发现此边的两个顶点庆卫镇,高山镇来自同一个连通图,舍去此边,找到下一条边,并对其进行判断。
    4.直到添加了n-1条边为止

在这里插入图片描述输入
第一行顶点个数你,边数m。
接下来的m行分别输入m条边的信息:对应的两个顶点的序号和权值(在这里顶点名为数字,当然也可以用字符使用strcmp函数)

#include<cstdio>
#include<iostream>
using namespace std;
const int M=20000;
int F[M];
int n,m;

struct Edge{//
    int u,v,w;
}edges[200000];
bool cmp(Edge a,Edge b){
    return a.w<b.w;
}
int Find(int x)
{
    if(F[x]==-1){
        return x;
    }else{
        return F[x]=Find(F[x]);//有一点回溯算法的意思,找到此连通图最原始的顶点。
    }
    
}
int kruskal(int n){
    sort(edges,edges+m, cmp);
    int cnt=0;
    int ans=0;
    for(int i=0;i<m;i++){
        int u=edges[i].u;
        int v=edges[i].v;
        int w=edges[i].w;
        int t1=Find(u);
        int t2=Find(v);
        if(t1!=t2){//如果两个点分别来自不同的连通图
            ans+=w;
            F[t1]=t2;//t1点与t2点相连
            cnt++;
        }
        if(cnt==n-1){
            break;
        }
    }
    if(cnt<n-1){
        return -1;
    }else{
        return ans;
    }
}
int main()
{
    memset(F, -1, sizeof(F));//初始化:每个顶点都不与其他顶点相连
    cin>>n>>m;
    for(int i=0;i<m;i++){
        int a,b,w;
        cin>>a>>b>>w;
        edges[i]={a,b,w};
    }
    cout<<kruskal(n)<<endl;
    return 0;
}

结果:

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

离婚带一娃要你管

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值