C语言实现最小生成树问题(Kruskal算法) - 乡村交通畅通工程
C语言实现最小生成树问题(Kruskal算法) - 乡村交通畅通工程
题目描述
某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离。省政府'畅通工程'的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小。请计算最小的公路总长度。
输入
测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( < 100 );随后的N(N-1)/2行对应村庄间的距离,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间的距离。为简单起见,村庄从1到N编号。
当N为0时,输入结束,该用例不被处理。
输出
对每个测试用例,在1行里输出最小的公路总长度。
样例输入
3
1 2 1
1 3 2
2 3 4
4
1 2 1
1 3 4
1 4 1
2 3 3
2 4 2
3 4 5
0
样例输出
3
5
思路:Kruskal算法
Kruskal算法是一种贪心算法,用于求解最小生成树问题,可以用于本题。
具体思路如下:
- 将所有边按照权值从小到大排序。
- 依次选取边,若选取的边连接的两个点不在同一个连通块中,则将这条边加入最小生成树中,并将这两个点合并到同一个连通块中。
- 当最小生成树中有N-1条边时,停止算法。
算法结束后,最小生成树的边权和即为最小的公路总长度。
代码:
#include <stdio.h>
#include <stdlib.h>
#define MAXN 100
struct Edge {
int u, v, w;
};
int N, E;
struct Edge edges[MAXN * MAXN];
int father[MAXN];
int cmp(const void *a, const void *b) {
return ((struct Edge *)a)->w - ((struct Edge *)b)->w;
}
void init() {
for (int i = 1; i <= N; i++) {
father[i] = i;
}
}
int find(int x) {
if (father[x] == x) {
return x;
} else {
return father[x] = find(father[x]);
}
}
void union_set(int x, int y) {
int fx = find(x), fy = find(y);
if (fx != fy) {
father[fx] = fy;
}
}
int kruskal() {
int ans = 0, cnt = 0;
qsort(edges, E, sizeof(struct Edge), cmp);
for (int i = 0; i < E; i++) {
int u = edges[i].u, v = edges[i].v, w = edges[i].w;
if (find(u) != find(v)) {
union_set(u, v);
ans += w;
cnt++;
if (cnt == N - 1) {
break;
}
}
}
return ans;
}
int main() {
while (scanf('%d', &N) != EOF && N != 0) {
E = N * (N - 1) / 2;
for (int i = 0; i < E; i++) {
scanf('%d %d %d', &edges[i].u, &edges[i].v, &edges[i].w);
}
init();
printf('%d
', kruskal());
}
return 0;
}
代码解析
Edge结构体用来存储每条边的信息,包括两个端点和权值。init()函数初始化并查集,每个节点的父节点初始化为自身。find()函数查找节点所属的连通块的根节点。union_set()函数合并两个连通块,将其中一个连通块的根节点设置为另一个连通块的根节点。kruskal()函数实现 Kruskal 算法,首先将所有边按照权值排序,然后依次选取边,如果这条边连接的两个点不在同一个连通块中,则将这条边加入最小生成树中,并将这两个点合并到同一个连通块中。main()函数读取输入数据,调用kruskal()函数计算最小生成树的边权和,并输出结果。
注意
- 本代码中,村庄从 1 到 N 编号,如果需要从 0 到 N-1 编号,需要对代码进行相应的修改。
- 本代码中,边权为正整数,如果需要处理负权值边,需要对代码进行相应的修改。
优化
- 可以使用并查集优化 find() 函数的时间复杂度,例如使用路径压缩或按秩合并等技术。
- 可以使用堆或优先队列优化边的排序操作。
希望本代码和解析能够帮助你理解 Kruskal 算法并解决乡村交通畅通工程问题。
原文地址: https://www.cveoy.top/t/topic/n8kI 著作权归作者所有。请勿转载和采集!