给定一个包含 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
,如果 aa 和 bb 在同一个连通块中,则输出 Yes
,否则输出 No
。
对于每个询问指令 Q2 a
,输出一个整数表示点 aa 所在连通块中点的数量
每个结果占一行。
数据范围
1≤n,m≤1051
输入样例:
5 5
C 1 2
Q1 1 2
Q2 1
C 2 5
Q2 5
输出样例:
Yes
2
3
#include<cstring>
#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
#include<map>
#include<cmath>
//#include<unordered_map>
#include<string>
#include<stack>
#include<queue>
#include<set>
#include<stdlib.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 2;
int par[N],siz[N];
int n,m,ans;
void init(int q)
{
for (int i = 0;i <= q;i++)
{
par[i] = i;
siz[i] = 1;//初始化,每个都是独立的块
}
}
int findd(int x)
{
if (par[x] != x)par[x] = findd(par[x]);
return par[x];
}
int main()
{
cin >> n >> m;
init(n);
while (m--)
{
string s;
int a, b;
cin >> s;
if (s[0] == 'C')
{
cin >> a >> b;
if (findd(a) == findd(b))
{
continue;
}
siz[findd(b)] += siz[findd(a)];//将a的祖宗节点接入b的祖宗节点,所以就是b+=a
par[findd(a)] = findd(b);
}
else
{
if (s[1] == '1')
{
cin >> a >> b;
if (par[findd(a)] == par[findd(b)])
{
cout << "Yes" << endl;
}
else
{
cout << "No" << endl;
}
}
else
{
cin >> a;
cout << siz[findd(a)] << endl;
}
}
}
}