【算法】【并查集】acwing算法基础837.连通块中点的数量
- 人工智能
- 2025-09-17 05:21:02

题目
给定一个包含 n 个点(编号为 1∼n)的无向图,初始时图中没有边。
现在要进行 m 个操作,操作共有三种:
C a b,在点 a 和点 b 之间连一条边,a和 b 可能相等;Q1 a b,询问点 a 和点 b 是否在同一个连通块中,a 和 b 可能相等; Q2 a,询问点 a 所在连通块中点的数量;
输入格式
第一行输入整数 n 和 m。
接下来 m 行,每行包含一个操作指令,指令为 C a b,Q1 a b 或 Q2 a 中的一种。
输出格式
对于每个询问指令 Q1 a b,如果 a 和 b 在同一个连通块中,则输出 Yes,否则输出 No。
对于每个询问指令 Q2 a,输出一个整数表示点 a 所在连通块中点的数量
每个结果占一行。
数据范围
1≤n,m≤105
输入样例:
5 5
C 1 2
Q1 1 2
Q2 1
C 2 5
Q2 5
输出样例:
Yes
2
3
来源:acwing算法基础837. 连通块中点的数量
思路(注意事项)
纯代码 #include<bits/stdc++.h> using namespace std; const int N = 100010; int p[N], si[N]; int find(int x) { if (p[x] != x) p[x] = find(p[x]); return p[x]; } int main() { int n, m; cin >> n >> m; for (int i = 1; i <= n; i++) { p[i] = i; si[i] = 1; } while (m --) { char c[2]; int a, b; scanf("%s", c); if (c[0] == 'C') { scanf("%d%d", &a, &b); if (find(a) == find(b)) continue; si[find(b)] += si[find(a)]; p[find(a)] = find(b); } else if (c[1] == '1') { scanf("%d%d", &a, &b); if (find(a) == find(b)) cout << "Yes" << endl; else cout << "No" << endl; } else { scanf("%d", &a); cout << si[find(a)] << endl; } } return 0; } 题解(带注释) #include<bits/stdc++.h> using namespace std; const int N = 100010; // 定义最大节点数 int p[N]; // 并查集数组,p[i] 表示节点 i 的父节点 int si[N]; // 存储每个集合的大小,si[i] 表示以 i 为根节点的集合的大小 // 查找函数,用于查找节点 x 的根节点,并进行路径压缩 int find(int x) { // 如果 x 不是根节点,递归查找其父节点的根节点,并进行路径压缩 if (p[x] != x) p[x] = find(p[x]); // 返回 x 的根节点 return p[x]; } int main() { int n, m; // n 表示节点数,m 表示操作数 cin >> n >> m; // 输入节点数和操作数 // 初始化并查集 for (int i = 1; i <= n; i++) { p[i] = i; // 每个节点的父节点初始化为自己 si[i] = 1; // 每个集合的大小初始化为 1 } // 处理每个操作 while (m --) { char c[2]; // 操作类型 int a, b; // 操作涉及的两个节点 scanf("%s", c); // 输入操作类型 if (c[0] == 'C') // 如果是合并操作 { scanf("%d%d", &a, &b); // 输入要合并的两个节点 if (find(a) == find(b)) continue; // 如果已经在同一个集合中,跳过 si[find(b)] += si[find(a)]; // 将 a 所在集合的大小加到 b 所在集合的大小上 p[find(a)] = find(b); // 将 a 所在集合的根节点的父节点设置为 b 所在集合的根节点 } else if (c[1] == '1') // 如果是查询操作(查询两个节点是否在同一个集合中) { scanf("%d%d", &a, &b); // 输入要查询的两个节点 if (find(a) == find(b)) cout << "Yes" << endl; // 如果在同一个集合中,输出 Yes else cout << "No" << endl; // 否则输出 No } else // 如果是查询操作(查询某个节点所在集合的大小) { scanf("%d", &a); // 输入要查询的节点 cout << si[find(a)] << endl; // 输出该节点所在集合的大小 } } return 0; }
【算法】【并查集】acwing算法基础837.连通块中点的数量由讯客互联人工智能栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“【算法】【并查集】acwing算法基础837.连通块中点的数量”