Kruskal算法构建最小生成树

本文详细介绍了克鲁斯卡尔算法构建图的最小生成树的过程,包括算法的具体步骤和示例。通过排序边的权值,逐个检查边是否形成环路来构建最小生成树。同时,给出了使用C++实现该算法的代码,利用并查集检测环路,确保生成的树不含环,并计算最小生成树的总权重。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


Kruskal算法原理:

(1)将图结构中的边按照权值从小到大进行排序处理。
(2)每次取其中权值最小的边考虑加入到最小生成树集合中。
(3)判断每次取的边加入到最小生成树中之后是否会形成环,如果会形成环则不能将该边加入到最小生成树集合中。
(4)重复步骤2、3。直到满足 顶点数 - 边数量 = 1,则说明最小生成树构建完成。

具体步骤如下:

图结构如下
在这里插入图片描述
(1)根据边的权值对边进行排序处理得到结果如下图所示:
在这里插入图片描述
(1)取6-7构成的边加入到最小生成树集合中,显然不会构成环,则该边可以加入到最小生成树集合中
在这里插入图片描述

(2)取2-8构成的边加入到最小生成树集合中,显然不会构成环,则该边可以加入到最小生成树集合中
在这里插入图片描述

(3)取5-6构成的边加入到最小生成树集合中,显然不会构成环,则该边可以加入到最小生成树集合中
在这里插入图片描述

(4)取0-1构成的边加入到最小生成树集合中,显然不会构成环,则该边可以加入到最小生成树集合中
在这里插入图片描述

(5)取2-5构成的边加入到最小生成树集合中,显然不会构成环,则该边可以加入到最小生成树集合中
在这里插入图片描述

(6)取6-8构成的边加入到最小生成树集合中,此时构成环路,则不能将该边加入到最小生成树集合中
在这里插入图片描述

(7)取7-8构成的边加入到最小生成树集合中,此时构成环路,则不能将该边加入到最小生成树集合中
在这里插入图片描述

(8)取2-3构成的边加入到最小生成树集合中,显然不会构成环,则该边可以加入到最小生成树集合中
在这里插入图片描述

(9)取0-7构成的边加入到最小生成树集合中,显然不会构成环,则该边可以加入到最小生成树集合中
在这里插入图片描述

(10)取1-2构成的边加入到最小生成树集合中,此时构成环路,则不能将该边加入到最小生成树集合中
在这里插入图片描述

(11)取3-4构成的边加入到最小生成树集合中,显然不会构成环,则该边可以加入到最小生成树集合中
此时最小生成树集合中边的数量为8条,顶点个数为9,满足顶点数 - 边数 = 1,所以已经找到了构成最小生成树的边。
在这里插入图片描述

代码实现

代码中需要用到并查集来检测环路。如果能构成最小生成树则输出最小生成树的边的权值之和否则输出-1。

//并查集找根节点
int find(const vector<int>& parent, int x){
	while(parent[x] != x){
		x = parent[x];
	}
	return x;
}

//合并
void merge(vector<int>& parent, int x, int y){
	int x_root = find(parent, x);
	int y_root = find(parent, y);
	parent[x_root] = y_root;
}
//仿函数
class mycompare{
	public:
		bool operator()(const vector<int>& v1, const vector<int>& v2){
			return v1[2] < v2[2];
		}
};

int minTree(int n, vector<vector<int>>& connections) {
//n表示顶点数
//conections = [[1,2,5],[1,3,6],[2,3,1]] 表示1-2边权值为5,1-3边权值为6,2-3边权值为1 
//顶点序号从1开始
	vector<int> parent(n + 1, 0);
	int count = 0;//统计边的数量
	for(int i = 1; i < parent.size(); ++i){
		parent[i] = i;
	}
	int res = 0;
	sort(connections.begin(), connections.end(), mycompare());
	for(int i = 0; i < connections.size(); ++i){
		if(find(parent, connections[i][0]) != find(parent, connections[i][1])){
			merge(parent, connections[i][0], connections[i][1]);
			res += connections[i][2];
			count++;
		}
	}
	return (count == n - 1 ? res : -1);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值