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;
}