U514565 连通块中点的数量
题目背景
在某个科学实验室中,有一组编号为 (1∼n) 的研究节点,初始时,这些节点之间没有任何连接。实验需要对这些节点进行动态操作并回答相关查询。实验设计如下:
题目描述
实验需要支持以下三种操作:
添加边操作
格式:C a b
在节点 (a) 和节点 (b) 之间建立一条边((a) 和 (b) 可以相同)。连通性查询操作
格式:Q1 a b
判断节点 (a) 和节点 (b) 是否在同一个连通块中,输出Yes
或No
。连通块大小查询操作
格式:Q2 a
查询节点 (a) 所在连通块中节点的数量。
输入格式
- 第一行输入两个整数 (n) 和 (m),分别表示节点数量和操作数量。
- 接下来的 (m) 行,每行包含一个操作,操作类型为
C a b
、Q1 a b
或Q2 a
。
输出格式
- 对于每个
Q1 a b
操作,输出Yes
或No
。 - 对于每个
Q2 a
操作,输出一个整数,表示连通块的节点数量。
每个结果占一行。
思路
知识点:并查集
最主要的是find()函数。
在操作3使用一个新的数组存储每一个节点对应连通块的中节点的个数。使用根节点来存储数据,访问连通块的节点个数的时候,访问根节点对应sum[]中的值即可。
代码
#include<bits/stdc++.h>
using namespace std;const int N = 100010;int n, m;
int p[N], sum[N];int find(int x){//返回x的祖宗节点加路径压缩if(p[x] != x)p[x] = find(p[x]);return p[x];//x的祖宗节点是x
}int main()
{scanf("%d %d", &n, &m);//初始化根节点,所有的根节点都是自己for(int i = 1; i <= n; i++){p[i] = i;sum[i] = 1;}for(int i = 0; i < m; i++){char op[3];scanf("%s", op);if(op[0] == 'C'){//连个节点之间进行连接 int a, b;scanf("%d %d", &a, &b);if(find(a) == find(b))continue; int x = sum[find(a)];sum[find(b)] += x;p[find(a)] = find(b);}else if(op[0] == 'Q' && op[1] == '1'){//连通性查询 int a, b;scanf("%d %d", &a, &b);if(find(a) == find(b)){puts("Yes");}else{puts("No");}}else{int a;scanf("%d", &a);printf("%d\n", sum[find(a)]);}}return 0;
}