Kruskal布鲁斯卡尔算法

Kruskal算法

是一种用来查找最小生成树的算法,由Joseph Kruskal在1956年发表。用来解决同样问题的还有Prim算法和Boruvka算法等。三种算法都是贪心算法的应用。和Boruvka算法不同的地方是,Kruskal算法在图中存在相同权值的边时也有效。

步骤

1.新建图G,G中拥有原图中相同的节点,但没有边;
2.将原图中所有的边按权值从小到大排序;
3.从权值最小的边开始,如果这条边连接的两个节点于图G中不在同一个连通分量中,则添加这条边到图G中;
4.重复3,直至图G中所有的节点都在同一个连通分量中。

时间复杂度

平均时间复杂度为O(|E|log|E|),其中E和V分别是图的边集和点集

C语言实现

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
 
const int M = 1e5+7;
 
struct node
{
  int a,b,val;
} Q[M];
int fa[M];
 
int Rd()
{
  int res=0;char c;
  while(c=getchar(),!isdigit(c));
  do {
    res=(res<<3)+(res<<1)+(c^48);
  } while(c=getchar(),isdigit(c));
  return res;
}
 
bool cmp(LZ a,LZ b){
  return a.val<b.val;
}
 
int getfa(int v){
    if(fa[v]!=v)fa[v]=getfa(fa[v]);
    return fa[v];
}
 
int main()
{
    int i,j,n,m,x,y;
    scanf("%d%d",&n,&m);
    for(i=1;i<=m;i++)
    {
        Q[i].a=Rd();Q[i].b=Rd();Q[i].val=Rd();
    }
    sort(Q+1,Q+m+1,cmp);
    for(i=1;i<=n;i++)
    {
        fa[i]=i;
    }
 
    int sum=0,cut=0;
    for(i=1;i<=m;i++)
    {
        x=getfa(Q[i].a);
        y=getfa(Q[i].b);        
        if(x==y)continue;        
        sum+=Q[i].val;        
        if(++cut==n-1)break;        
        fa[x]=y;    
    }    
    printf("%d",sum);    
    return 0;
}

猜你喜欢

转载自blog.csdn.net/king9666/article/details/87695845