码迷,mamicode.com
首页 > 编程语言 > 详细

最小生成树-kruskal算法

时间:2018-08-11 01:26:21      阅读:140      评论:0      收藏:0      [点我收藏+]

标签:code   权重   核心   pre   kruskal   问题   end   产生   连通   

连通图的一棵生成树是包含图的所有顶点的连通无环子图。

加权连通图的一棵最小生成树是图的一棵权重最小的生成树,其中,树的权重定义为所有边的权重总和。

最小生成树问题就是求一个给定的加权连通图的最小生成树问题。

最小生成树的算法主要有prim算法和kruskal算法,这篇主要讲解和实现后者。

kruskal算法主要是基于并查集+贪心的算法。该算法开始的时候,会按照权重的非递减顺序对所有的边进行排序,然后从一个空子图开始,扫描这个有序列表,并试图将列表中的下一条边加到当前的子图中。但是,如果加上这条边产生了回路,则把这条边跳过。

#include <iostream>
#include <algorithm>
using namespace std;
const int N=150;
int father[N],r[N],u[N],v[N],w[N];//定义father为每个节点的父亲,r为每条节点的编号,u,v为节点,w为边的权重
int find(int x)//并查集的核心算法,找寻父亲节点
{
    int r=x;
    while(father[r]!=r)
    {
        r=father[r];
    }
    return r;
}
bool cmp(const int a,const int b)//主要用于sort函数中对于边的权重的排序
{
    return w[a]<w[b];
}
int kruskal(int n,int m)//核心算法
{
    int mst=0,cnt=0;
    for(int i=0;i<n;i++)//初始化每个节点的父亲为自己本身
    {
        father[i]=i;
    }
    for(int i=0;i<m;i++)//记录每条边的序号
    {
        r[i]=i;
    }
    sort(r,r+m,cmp);//将边按照权重从小到大排序,这里只改变序号,就可以知道是哪条边
    for(int i=0;i<m;i++)//对每条边来说,都判断边的两个顶点是否连通,如果连通,则证明加入之后,会出现回路,不予考虑
    {
        int e=r[i];
        int x=find(u[e]);
        int y=find(v[e]);
        if(x!=y)
        {
            mst+=w[e];
            father[x]=y;
            cnt++;
        }
    }
    if(cnt<n-1)//证明此图不连通,不存在最小生成树
        mst=0;
    return mst;
}
int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=0;i<m;i++)
    {
        cin>>u[i]>>v[i]>>w[i];
    }
    int mst=kruskal(n,m);
    if(mst==0)
        cout<<"the mst is not found"<<endl;
    else
        cout<<"the mst is  "<<mst<<endl;
    return 0;
}

 

最小生成树-kruskal算法

标签:code   权重   核心   pre   kruskal   问题   end   产生   连通   

原文地址:https://www.cnblogs.com/mini-coconut/p/9457932.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!