1. 程式人生 > 實用技巧 >【連通塊 維護size】 連通塊中的點數

【連通塊 維護size】 連通塊中的點數

傳送門

題意

給定一個包含\(n\)個點(編號為\(1\sim n\))的無向圖,初始時圖中沒有邊。
現在要進行\(m\)個操作,操作共有三種:

  1. (C,a,b),在點a和點b之間連一條邊,a和b可能相等;
  2. (Q1,a,b),詢問點a和點b是否在同一個連通塊中,a和b可能相等;
  3. (Q2,a),詢問點a所在連通塊中點的數量;

資料範圍

\(1\leq n,m\leq 10^{5}\)

題解

維護集合數目的並查集,合併的時候將集合的數目合併即可

Code

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define close ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define ll long long
int _;
const int N=1e5+10;
int fa[N],sz[N];
int find(int x){
    if(fa[x]!=x) fa[x]=find(fa[x]); 
    return fa[x];
}
void merge(int a,int b){
    int fa_a=find(a),fa_b=find(b);
    if(fa_a==fa_b) return;
    sz[fa_b]+=sz[fa_a];
    fa[fa_a]=fa_b;
}
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    rep(i,1,n+1) fa[i]=i,sz[i]=1;
    char op[3];
    while(m--){
        int a,b;
        scanf("%s",op);
        scanf("%d",&a);
        if(op[0] == 'C'){
            scanf("%d",&b);
            if(a!=b) merge(a,b);
        }
        else if(op[1]=='1'){
            scanf("%d",&b);
            if(find(a) == find(b)) puts("Yes");
            else puts("No");
        }
        else 
            printf("%d\n",sz[find(a)]);
    }
}