Kruskal算法

Kruskal算法是一种按权值的递增次序选择合适的边来构造最小生成树的方法。

对于给定的一张图,其算法思路:

  1. 将边按权值升序排序;
  2. 选出权值最小的边加入到最小生成树中,如果产生回路就放弃这条边(利用并查集来判断是否产生回路);
  3. 重复步骤2,直到所有顶点都加入最小生成树中;

算法过程图:

 

将图的边按权值排序,每个顶点放在单独的集合里:

(1)选出权值最小的边(0,2)加入到最小生成树中,顶点0和2不在同一集合,没产生回路。合并顶点0和2所在的集合。

(2)选出权值最小的边(3,5)加入到最小生成树中,顶点3和5不在同一集合,没产生回路。合并顶点3和5所在的集合。

(3)选出权值最小的边(1,4)加入到最小生成树中,顶点1和4不在同一集合,没产生回路。合并顶点1和4所在的集合。

(4)选出权值最小的边(2,5)加入到最小生成树中,顶点2和5不在同一集合,没产生回路。合并顶点2和5所在的集合。

(5)选出权值最小的边(0,3)加入到最小生成树中,顶点0和3在同一集合中,产生回路,故放弃这条边。再选出权值最小的边(1,2)加入到最小生成树中,顶点1和2不在同一集合,没产生回路。合并顶点1和2所在的集合。

至此所有顶点都在同一个集合中,一颗最小生成树就构造完成。

模板函数:

const int INF = 0x3f3f3f3f;
const int N = 55;
int map[N][N]; //邻接矩阵存图 
int Set[N];    //并查集 
int n;         //n个顶点 
struct Edge
{
	int x,y; //顶点x,y 
	int weight;//权值 
	bool operator< (const Edge &x)const //比较权值大小 
	{
		return weight<x.weight;
	}
}e[N*N];
void init() //初始化并查集 
{
	for(int i=1;i<=n;i++)
		Set[i]=i;
}
int Find(int x)//查找根节点 
{
	if(x==Set[x])
		return x;
	return Set[x]=Find(Set[x]);
}
bool Union(int x,int y)//合并集合 
{
	x=Find(x);
	y=Find(y);
	if(x==y)
		return false;
	if(x>y)
		Set[x]=y;
	else
		Set[y]=x;
	return true;
}
int Kruskal(int m)//m条边 
{
	init();                      //初始并查集 
	sort(e,e+m);			     //按边权值升序排序 
	int cnt=0;                   //统计最小生成树上的边数 
	int res=0;					 //累加最小生成树的所有边权值和 
	for(int i=0;i<m;i++)	     //遍历所有边 
	{							
		if(Union(e[i].x,e[i].y)) //判断两个顶点是否在同一集合(是否构成回路) 
		{
			cnt++;               //没有构成回路,最小生成树的边数+1 
			res+=e[i].weight;	 //累加权值 
		}
		if(cnt==n-1)             //找到最小生成树上的n-1条边说明最小生成树构造完成 
			return res;          //返回权值和 
	}
	return res;
}	

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值