【連通塊 維護size】 連通塊中的點數
阿新 • • 發佈:2020-08-03
傳送門
題意
給定一個包含\(n\)個點(編號為\(1\sim n\))的無向圖,初始時圖中沒有邊。
現在要進行\(m\)個操作,操作共有三種:
(C,a,b)
,在點a和點b之間連一條邊,a和b可能相等;(Q1,a,b)
,詢問點a和點b是否在同一個連通塊中,a和b可能相等;(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)]); } }