经典的并查集求无向图连通分量的题目
每读入一组数据,都将其合并进之前的图中
最后统计有几个人与给定的ai处于同一图中即可
#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
// 递归查找祖先
int Find(vector<int>& parent, int index) {
if (parent[index] != index) {
parent[index] = Find(parent, parent[index]);
}
return parent[index];
}
// 合并
void Union(vector<int>& parent, int index1, int index2) {
int p1 = Find(parent, index1);
int p2 = Find(parent, index2);
parent[p1] = p2; // 将p1的祖先设置为p2
}
int main() {
int n, ai, m;
cin >> n >> ai >> m;
// 并查集 初始化
vector<int> parent(n, 0);
for (int i = 0; i < n; i++) {
parent[i] = i;
}
int alknown = 0; // ai事先认识的数量
int a, b;
for (int i = 0; i < m; i++) {
scanf("%d,%d", &a, &b);
if (a == ai || b == ai) {
alknown++;
}
Union(parent, a, b);
}
int ans = 0;
for (int i = 0; i < n; i++) {
// 如果i和ai处于同一个连通分量中
if (Find(parent, i) == Find(parent, ai)) {
ans++;
}
}
// 注意减去ai事先认识的人数量,再减去ai自己
cout << ans - alknown - 1 << endl;
return 0;
}
时间复杂度:
1、初始化并查集,耗时 O(n) ,其中 n 是总人数
2、遍历 m 条边并进行合并操作的时间复杂度为 O(m * α(n)),其中 α(n) 是 Ackermann 函数的反函数,可以看作是一个非常小的常数
3、遍历所有人并统计与 ai 在同一个连通分量中的人数的时间复杂度为 O(n)
综上,时间复杂度为 O(n + m * α(n))
空间复杂度:O(n) ,用于存储 parent 数组

京公网安备 11010502036488号