第一行输入节点个数(n<=2000000)和边数(m<=2030000),然后下面每一行为边的头尾节点。要求输出连通分量的个数。请编写C语言代码。
时间: 2025-02-02 14:11:55 浏览: 14
为了计算给定无向图的连通分量数,我们可以使用并查集数据结构。以下是基于这个思路的一个简单的C语言代码示例:
#include <stdio.h>
#include <stdlib.h>
// 定义并查集
typedef struct {
int parent[2000001]; // 使用数组存储每个节点的根节点索引
int rank[2000001]; // 存储每个集合的秩(用于快速合并)
} UnionFind;
void initUnionFind(UnionFind* uf) {
for (int i = 0; i <= 2000000; ++i) {
uf->parent[i] = i;
uf->rank[i] = 0;
}
}
int findSet(int uf[], int node) {
if (uf[node] == node) { // 如果当前节点就是其根节点
return node;
} else {
// 如果当前节点不是其根节点,则往上追溯,直到找到根节点
uf[node] = findSet(uf, uf[node]);
return uf[node];
}
}
void unionSets(UnionFind* uf, int nodeA, int nodeB) {
int rootA = findSet(uf, nodeA);
int rootB = findSet(uf, nodeB);
// 如果两个节点不在同一个集合中
if (rootA != rootB) {
// 合并两个集合,通过将较小集合的根赋值给较大集合的根
if (uf->rank[rootA] < uf->rank[rootB]) {
uf->parent[rootA] = rootB;
} else {
uf->parent[rootB] = rootA;
// 如果秩相等,提升根节点的秩防止未来的循环合并
if (uf->rank[rootA] == uf->rank[rootB]) {
uf->rank[rootA]++;
}
}
}
}
int main() {
int n, m; // 输入节点数和边数
scanf("%d %d", &n, &m);
UnionFind uf;
initUnionFind(&uf);
// 遍历每条边,加入到并查集中
for (int i = 0; i < m; i++) {
int u, v;
scanf("%d %d", &u, &v);
unionSets(&uf, u, v);
}
// 计算连通分量数量
int cnt = 0;
for (int i = 1; i <= n; i++) {
if (findSet(uf.parent, i) == i) { // 找到根节点即是一个连通分量
cnt++;
}
}
printf("连通分量的数量: %d\n", cnt);
return 0;
}
这个程序首先初始化了一个并查集结构,接着读入节点数和边数以及每条边的节点,然后通过unionSets
函数将它们合并到相应的连通分量中。最后,遍历所有节点,统计未连接到其他节点的根节点数量,即为连通分量的数量。
相关推荐















