C语言实现带权连通图最小生成树 - 破圈法
C语言实现带权连通图最小生成树 - 破圈法
'破圈法'是求带权连通图的最小生成树的一种方法,其思路是任意取一个圈,去掉圈上权最大的一个边,反复执行这个步骤,直到图中没有圈为止。
代码实现
#include <stdio.h>
#include <stdlib.h>
#define MAX_VERTEX_NUM 100
#define MAX_EDGE_NUM 1000
typedef struct {
int from;
int to;
int weight;
} Edge; // 定义边
typedef struct {
int vertex;
int parent;
} UnionFind; // 定义并查集结构体
void swap(Edge* a, Edge* b) {
Edge temp = *a;
*a = *b;
*b = temp;
}
void sort(Edge edgeList[], int edgeNum) {
for (int i = 0; i < edgeNum - 1; i++) {
for (int j = i + 1; j < edgeNum; j++) {
if (edgeList[i].weight > edgeList[j].weight) {
swap(&edgeList[i], &edgeList[j]);
}
}
}
}
int find(UnionFind ufSet[], int x) {
int root = x;
while (ufSet[root].parent >= 0) {
root = ufSet[root].parent;
}
while (x != root) {
int parent = ufSet[x].parent;
ufSet[x].parent = root;
x = parent;
}
return root;
}
void merge(UnionFind ufSet[], int x, int y) {
int root1 = find(ufSet, x);
int root2 = find(ufSet, y);
if (ufSet[root1].parent < ufSet[root2].parent) {
ufSet[root1].parent += ufSet[root2].parent;
ufSet[root2].parent = root1;
} else {
ufSet[root2].parent += ufSet[root1].parent;
ufSet[root1].parent = root2;
}
}
void kruskal(Edge edgeList[], int edgeNum, int vertexNum) {
UnionFind* ufSet = (UnionFind*)malloc(sizeof(UnionFind) * vertexNum);
for (int i = 0; i < vertexNum; i++) {
ufSet[i].vertex = i;
ufSet[i].parent = -1;
}
int edgeCount = 0;
int minWeightSum = 0;
for (int i = 0; i < edgeNum; i++) {
int from = edgeList[i].from;
int to = edgeList[i].to;
if (find(ufSet, from) != find(ufSet, to)) {
merge(ufSet, from, to);
edgeCount++;
minWeightSum += edgeList[i].weight;
if (edgeCount == vertexNum - 1) {
break;
}
}
}
printf("Minimum weight sum: %d\n", minWeightSum);
free(ufSet);
}
int main() {
int vertexNum, edgeNum;
printf("Please enter the number of vertices and edges: ");
scanf("%d %d", &vertexNum, &edgeNum);
Edge* edgeList = (Edge*)malloc(sizeof(Edge) * edgeNum);
printf("Please enter the edges and weights:\n");
for (int i = 0; i < edgeNum; i++) {
scanf("%d %d %d", &edgeList[i].from, &edgeList[i].to, &edgeList[i].weight);
}
sort(edgeList, edgeNum);
kruskal(edgeList, edgeNum, vertexNum);
free(edgeList);
return 0;
}
代码说明
-
数据结构定义
Edge结构体表示图中的边,包含边的起点 (from)、终点 (to) 和权值 (weight)。UnionFind结构体表示并查集中的节点,包含节点编号 (vertex) 和父节点编号 (parent)。
-
函数说明
swap函数:交换两个Edge结构体。sort函数:对边列表进行排序,从小到大排序权值。find函数:查找并查集中节点的根节点。merge函数:合并并查集中两个集合。kruskal函数:使用 Kruskal 算法求最小生成树,并输出最小生成树的总权值。main函数:输入顶点数、边数和权值,调用kruskal函数求解最小生成树。
使用方法
- 编译并运行代码。
- 输入顶点数、边数和权值,以空格隔开。
- 输出最小生成树的总权值。
示例
输入:
4 5
0 1 1
0 2 3
1 2 2
1 3 4
2 3 5
输出:
Minimum weight sum: 6
总结
本代码实现了求带权连通图的最小生成树算法,使用破圈法,可以帮助理解最小生成树算法的原理和实现。
原文地址: https://www.cveoy.top/t/topic/owfG 著作权归作者所有。请勿转载和采集!