1. 程式人生 > 實用技巧 >【模板】 合併集合

【模板】 合併集合

傳送門

題意

\(n\)個數初始每個數都在一個集合,\(m\)個操作,

  1. (M,a,b),將編號為a和b的兩個數所在的集合合併,如果兩個數已經在同一個集合中,則忽略這個操作;
  2. (Q,a,n),詢問編號為a和b的兩個數是否在同一個集合中;

資料範圍

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

題解

並查集維護集合的查詢與合併,時間複雜度為\(O(n·log n)\)

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
const int N=1e5+10;
int fa[N];
int _;
int n,m;
int find(int x){
    if(fa[x] != x) fa[x]=find(fa[x]);
    return fa[x]; 
}
void merge(int a,int b){
    int pa=find(a),pb=find(b);
    if(pa!=pb) fa[pa]=pb;
}
int main(){
    scanf("%d%d",&n,&m);
    rep(i,1,n+1) fa[i]=i;
    char op[2];
    while(m--){
        int a,b;
        scanf("%s",op);
        scanf("%d%d",&a,&b);
        if(op[0] == 'M') merge(a,b);
        else {
            int pa=find(a),pb=find(b);
            if(pa==pb) puts("Yes");
            else puts("No");
        } 
    }
}