连通块中点的数量

给定一个包含 n 个点(编号为 1∼n)的无向图,初始时图中没有边。

现在要进行 m 个操作,操作共有三种:

  1. C a b,在点 𝑎 和点 b 之间连一条边,𝑎 和 b 可能相等;
  2. Q1 a b,询问点 𝑎 和点 b 是否在同一个连通块中,𝑎 和 b 可能相等;
  3. Q2 a,询问点 𝑎 所在连通块中点的数量;

输入格式

第一行输入整数 n 和 m。

接下来 m 行,每行包含一个操作指令,指令为 C a bQ1 a b 或 Q2 a 中的一种。

输出格式

对于每个询问指令 Q1 a b,如果 a𝑎 和 b𝑏 在同一个连通块中,则输出 Yes,否则输出 No

对于每个询问指令 Q2 a,输出一个整数表示点 a𝑎 所在连通块中点的数量

每个结果占一行。

数据范围

1≤n,m≤1e5

输入样例:

5 5
C 1 2
Q1 1 2
Q2 1
C 2 5
Q2 5

输出样例:

Yes
2
3

#include<iostream>
using namespace std;
const int N=100010;
int p[N],cnt[N];
int n,m;
int find(int x)
{
    if(p[x]!=x) return p[x]=find(p[x]);
    return p[x];
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;++i) p[i]=i,cnt[i]=1;
    while(m--)
    {
        string ch;
        int a,b;
        cin>>ch;
        if(ch=="C")
        {
            cin>>a>>b;
            if(find(a)!=find(b)) cnt[find(b)]+=cnt[find(a)];
            p[find(a)]=find(b);
        }
        else if(ch=="Q1")
        {
            cin>>a>>b;
            int pa=find(a);
            int pb=find(b);
            if(pa==pb) cout<<"Yes"<<endl;
            else cout<<"No"<<endl;
        }
        else
        {
            cin>>a;
            cout<<cnt[find(a)]<<endl;
        }
    }
    return 0;
}