并查集模板
主要用于处理一些不相交集合的合并问题,p[i] : i 所在集合的根节点,rank[i] : 以 i 为根节点展开的树的深度。
- 初始化:各元素自成一个集合,p[i] = i, rank[i] = 0。
- find(x):找到元素 x 所在的集合的根节点。注意在查找过程中进行路径压缩。
- union(x, y)(合并):把元素 x 和元素 y 所在的集合合并,要求 x 和 y 所在的集合不相交,如果相交则不合并。合并时候按 rank[x] 和 rank[y] 的大小合并。
/*==================================================*\
| 带权值的并查集
| INIT: init(n);
| CALL: find(x); unin(x, y);
\*==================================================*/
#include<bits/stdc++.h>
using namespace std;
constexpr int N = 10005;
struct lset {
int p[N], rank[N], sz; //p[N]:根节点,rank[N]:根节点展开的树的深度
void link(int x, int y) {
if (x == y)
return;
if (rank[x] > rank[y]) //x深度大于y,则y链到x下。
p[y] = x;
else
p[x] = y;
if (rank[x] == rank[y]) //如果深度相同且根节点不同,则新的根节点的深度+1
rank[y]++;
}
void init(int n) { //初始化
sz = n;
for (int i = 0;i < sz; i++) {
p[i] = i;
rank[i] = 0;
}
}
int find(int x) {
return x == p[x] ? x : (p[x] = find(p[x])); //将find(p[x])的值(即根)赋给p[x],路径压缩
}
void unin(int x, int y) {
link(find(x), find(y)); //合并两个集合,且保存集合根为其中的根节点之一
}
void compress() {
for (int i = 0; i < sz; i++)
find(i);
}
};
int main(){
int n, m;
cin >> n >> m;
lset t;
t.init(n+1);
while (m--) {
int z, x, y;
cin >> z >> x >> y;
if (z == 1)
t.unin(x, y);
else {
cout << (t.find(x) == t.find(y) ? 'Y' : 'N') << endl;
}
}
return 0;
}