Trace
连通块中点的数量
传送门:https://www.acwing.com/problem/content/839/
Problem
给定一个包含 nn 个点(编号为 1∼n1∼n)的无向图,初始时图中没有边。
现在要进行 mm 个操作,操作共有三种:
C a b
,在点 aa 和点 bb 之间连一条边,aa 和 bb 可能相等;
Q1 a b
,询问点 aa 和点 bb 是否在同一个连通块中,aa 和 bb 可能相等;
Q2 a
,询问点 aa 所在连通块中点的数量;
输入格式
第一行输入整数 nn 和 mm。
接下来 mm 行,每行包含一个操作指令,指令为 C a b
,Q1 a b
或 Q2 a
中的一种。
输出格式
对于每个询问指令 Q1 a b
,如果 aa 和 bb 在同一个连通块中,则输出 Yes
,否则输出 No
。
对于每个询问指令 Q2 a
,输出一个整数表示点 aa 所在连通块中点的数量
每个结果占一行。
数据范围
1≤n,m≤1e5
输入样例:
1 2 3 4 5 6
| 5 5 C 1 2 Q1 1 2 Q2 1 C 2 5 Q2 5
|
输出样例:
思路:
并查集基础模板题
$cnt[N]$:记录每个集合中元素个数
$p[N]$:存当前节点父结点,路径压缩后存根结点
合并集合时先合并数量,再连边。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| #include <bits/stdc++.h> using namespace std;
const int N=1e5+10;
int p[N];
int cnt[N];
int n,m;
int find(int x){ if(x!=p[x]) 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 s; cin>>s; int x,y; if(s=="Q2"){ cin>>x; cout<<cnt[find(x)]<<endl; } else if(s=="Q1"){ cin>>x>>y; if(find(x)==find(y)){ cout<<"Yes"<<endl; } else{ cout<<"No"<<endl; } } else{ cin>>x>>y; if(find(x)!=find(y)){ cnt[find(y)]+=cnt[find(x)]; p[find(x)]=find(y); } } } }
|
$find()$时间复杂度可以看成$O(1)$。