用C语言完成这道题目“给定一张 n 个点 m 条边的无重边和自环的无向图,求团的个数,对 1 0^9 + 7 取模。 一个非空点集 S 被成为团,当且仅当对于 S 中任意两个不同的节点 u,v,节点 u,v 被一条边直接相连”
时间: 2024-10-04 20:01:20 浏览: 41
在C语言中,这个问题可以使用并查集(Union-Find)数据结构来解决。这是一个用于寻找连通分量的算法,非常适合于计算无向图中的团(即所有顶点都是彼此相邻的集合)。以下是步骤:
1. 首先,创建一个大小为n的数组,每个元素初始化为数组下标本身,表示每个节点初始时都属于单独的一个集合。
2. 然后遍历每条边,对于每条连接u和v的边:
a. 使用并查集中find函数找到节点u和v所在的集合根(也就是它们所属的初始集合)。
b. 如果这两个集合的根不是同一个(说明它们之前没有被合并过),则执行union操作将这两个集合合并成一个新的集合,使得边上的节点属于同一个团。
3. 在整个过程中,统计并查集中集合的数量减一,因为初始集合也被计数了。这是因为并查集会自动合并相等的集合,所以最终集合数量就是团的数量。
4. 最后,返回结果并对1e9+7取模。由于题目要求对10^9 + 7取模,需要在每次加法操作之后更新答案。
```c
#include <stdio.h>
#define MAXN 100005
#define MOD 1000000007
int par[MAXN], sz[MAXN];
int find(int x) {
if (x == par[x]) return x;
return par[x] = find(par[x]);
}
void unite(int x, int y) {
x = find(x);
y = find(y);
if (x != y) {
if (sz[x] > sz[y]) swap(x, y); // 按照集合大小调整合并策略
par[y] = x; sz[x] += sz[y];
}
}
int main() {
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
par[i] = i;
sz[i] = 1;
}
int ans = n; // 初始团的数量等于节点数
while (m--) {
int u, v;
scanf("%d%d", &u, &v);
if (find(u) != find(v)) unite(u, v);
}
ans -= sz[1]; // 减去最大的集合,因为它会被多次计数
printf("%d\n", ((ans % MOD) + MOD) % MOD); // 对MOD取模
return 0;
}
```
阅读全文