最小生成树--Kruskal

最小生成树----Kruskal

Kruskal与Prim不同的是Prim是以任意一个点为起点,一次向其他点遍历,而Kruskal则是以边为起点,向其他边遍历,Kruskal的时间复杂度远远小于Prim。

思路:

  1. 先将所有的边排序
  2. 依次找出边权最小的边,并查集判断他是否以连接
  3. 如果未连接,则将其连接,并继续找剩下的最小的边
  4. 直到边数为(n-1)
            时间复杂度O(nlogn)

Code

#include<iostream>
#include<memory.h>//memset的头文件
#include<algorithm>//快速排序的头文件
using namespace std;
const int N=2e5+5;
int ans;
int n,m;//顶点数与边数
int fa[N];//并查集的父域
struct edge{
    int u,v;//边的起点与终点
    int cost;//边的权值
}e[N];
bool cmp(edge a,edge b)//结构体比较大小的函数
{
    return a.cost<b.cost;
}
void init(int n)//并查集初始化
{
    for(int i=1;i<=n;i++)
    fa[i]=i;
    return ;
}
int find(int x)//并查集函数
{
    if(fa[x]==x)
    return x;
    else 
    {
        fa[x]=find(fa[x]);
        return fa[x];
    }
}
int kruskal(int n,int m)
{
    int e_n=0;//已经建立的边数
    init(n);//初始化
    sort(e,e+m,cmp);//排序
    for(int i=1;i<=m-1;i++)
    {
        int fau=find(e[i].u);//边的起点的父域
        int fav=find(e[i].v);//边的终点的父域
        if(fau!=fav)//如果两个父域不同,则证明他们两个点未连接
        {
            fa[fau]=fav;//讲两个点连接起来
            ans+=e[i].cost;//讲边权累加
            //cout<<e[i].cost<<' ';
            e_n++;//边数加1
            if(e_n==n-1) break; //如果边数到达了n-1,则退出循环
        }    
    }
    if(e_n!=n-1) return -1;//判断是否构成一颗生成树
    else return 1;
}

int main()
{
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    e[i].cost=9999;//给每条边初始化最大值
    for(int i=1;i<=m;i++)
    {
        int w;
        cin>>e[i].u>>e[i].v>>w;
        e[i].cost=min(w,e[i].cost);//防止有重复输入的数据,取最小的
    }    
    if(kruskal(n,m)==-1) cout<<"orz"<<endl;
    else cout<<ans<<endl;
    return 0;
}
全部评论

相关推荐

02-15 22:29
门头沟学院 Java
点赞 评论 收藏
分享
01-17 12:35
吉首大学 Java
秋招之BrianGriffin:自己的工作自己做!😡
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务