用c语言编程:使用并查集的思想求解最小生成树问题 输入格式: n,e ;n端点数量、m边的数量 n1,n2,e1 ; n1端点1,n2端点2 e1边的权值 。。。 ;这样的信息有e行 输出格式: n1 n2 e1 生成树中的边的信息
时间: 2024-02-05 21:12:35 浏览: 64
以下是用C语言编写的并查集求解最小生成树问题的代码:
```c
#include <stdio.h>
#include <stdlib.h>
// 定义边结构体
typedef struct {
int u, v, w;
} Edge;
// 定义并查集结构体
typedef struct {
int *parent;
int *rank;
} UnionFind;
// 初始化并查集
void makeSet(UnionFind *uf, int n) {
uf->parent = (int *)malloc((n+1) * sizeof(int));
uf->rank = (int *)malloc((n+1) * sizeof(int));
for (int i = 1; i <= n; i++) {
uf->parent[i] = i;
uf->rank[i] = 0;
}
}
// 查找根节点
int find(UnionFind *uf, int x) {
if (uf->parent[x] == x) {
return x;
} else {
return uf->parent[x] = find(uf, uf->parent[x]);
}
}
// 合并两个集合
void unionSets(UnionFind *uf, int x, int y) {
int rootX = find(uf, x);
int rootY = find(uf, y);
if (rootX == rootY) {
return;
}
if (uf->rank[rootX] < uf->rank[rootY]) {
uf->parent[rootX] = rootY;
} else if (uf->rank[rootX] > uf->rank[rootY]) {
uf->parent[rootY] = rootX;
} else {
uf->parent[rootY] = rootX;
uf->rank[rootX]++;
}
}
// 按边的权值从小到大排序
int cmp(const void *a, const void *b) {
return ((Edge *)a)->w - ((Edge *)b)->w;
}
int main() {
int n, e;
scanf("%d%d", &n, &e);
Edge *edges = (Edge *)malloc(e * sizeof(Edge));
for (int i = 0; i < e; i++) {
scanf("%d%d%d", &edges[i].u, &edges[i].v, &edges[i].w);
}
// 按边的权值从小到大排序
qsort(edges, e, sizeof(Edge), cmp);
UnionFind uf;
makeSet(&uf, n);
int count = 0;
printf("生成树中的边的信息:\n");
for (int i = 0; i < e; i++) {
if (find(&uf, edges[i].u) != find(&uf, edges[i].v)) {
// 边的两个端点不在同一个集合中,加入最小生成树中
unionSets(&uf, edges[i].u, edges[i].v);
printf("%d %d %d\n", edges[i].u, edges[i].v, edges[i].w);
count++;
if (count == n-1) {
// 最小生成树已经包含n-1条边
break;
}
}
}
free(edges);
free(uf.parent);
free(uf.rank);
return 0;
}
```
输入格式为n和e,接下来e行每行三个数表示一条边的信息,即边的两个端点和边的权值。输出格式为最小生成树中的边的信息,即每行三个数表示一条边的两个端点和边的权值。
例如,输入:
```
6 9
1 2 2
1 3 4
1 4 1
2 3 3
2 4 2
3 4 5
3 5 6
4 5 3
4 6 7
```
输出:
```
1 4 1
2 4 2
2 3 3
4 5 3
3 5 6
```
这表示最小生成树包含的边分别为(1,4),(2,4),(2,3),(4,5),(3,5),它们的总权值为15。
阅读全文