(1)朴素并查集:=》只判连通
cpp
int p[N]; // 存储每个点的祖宗节点
// 查找 + 路径压缩(核心)
int find(int x)
{
if (p[x] != x)
p[x] = find(p[x]); // 路径直接挂到根节点
return p[x];
}
// 初始化:每个点自己是根
for (int i = 1; i <= n; i ++ )
p[i] = i;
// 合并 a 和 b 所在集合
p[find(a)] = find(b);
(2)带集合大小的并查集:=》统计集合元素个数(连不连通 + 集合多大)
cpp
int p[N], size[N];
// p[]:存储每个点的祖宗节点
// size[]:只有祖宗节点有效,表示当前集合的元素数量
// 查找 x 的根节点 + 路径压缩
int find(int x)
{
if (p[x] != x)
p[x] = find(p[x]);
return p[x];
}
// 初始化:每个点自己是根,集合大小为 1
void init(int n)
{
for (int i = 1; i <= n; i ++ )
{
p[i] = i;
size[i] = 1;
}
}
// 合并 a 和 b 所在的集合
void merge(int a, int b)
{
int fa = find(a);
int fb = find(b);
if (fa != fb)
{
// 先更新集合大小,再修改父节点(顺序不能变)
size[fb] += size[fa];
p[fa] = fb;
}
}
(3)维护到祖宗节点距离的并查集:=》维护点到根的距离/关系(连不连通 + 两点之间距离 / 关系)
cpp
int p[N], d[N];
// p[x]:存储节点 x 的父节点
// d[x]:存储 x 到其父节点 p[x] 的距离/权值(find后表示x到根节点的距离)
// 查找 x 的根节点 + 路径压缩 + 维护距离
int find(int x)
{
if (p[x] != x)
{
// 先递归找到根节点 u
int u = find(p[x]);
// 更新 x 到根节点的距离
d[x] += d[p[x]];
// 路径压缩:直接把 x 挂到根节点上
p[x] = u;
}
return p[x];
}
// 初始化:每个节点自己是根,到父节点距离为 0
void init(int n)
{
for (int i = 1; i <= n; i ++ )
{
p[i] = i;
d[i] = 0;
}
}
// 合并 a 和 b 所在集合(根据题目自定义 distance)
void merge(int a, int b, int distance)
{
int fa = find(a);
int fb = find(b);
if (fa != fb)
{
p[fa] = fb;
d[fa] = distance; // 核心:设置根 fa 到根 fb 的权值
}
}
cpp
#include<bits/stdc++.h>
using namespace std;
const int N = 1e4+10;
int p[N];
int find(int x){
if(p[x]!=x){
p[x]=find(p[x]);
}
return p[x];
}
int main(){
int n;
int maxnum = 0;
if(!(cin>>n)) return 0;
for(int i = 0;i<N;i++) p[i] = i;
for(int i = 0 ;i <n;i++){
int k;
if(!(cin>>k)) return 0;
vector<int> a(k);
for(int j = 0;j<k;j++ ){
int x;
cin>>x;
if(x>maxnum) maxnum = x;
a[j] = x;
}
if(k<2) continue;
for(int j = 0;j<k-1;j++){
int x = find(a[j]);
int y = find(a[j+1]);
if(x!=y){
p[y] = x;
}
}
}
set<int> mp;
//p[i] = 父节点,不一定是根
//find(i) = 一定是根
for(int i = 1;i<=maxnum;i++){
mp.insert(find(i));
}
cout<<maxnum<<" "<<mp.size()<<endl;
int q;
cin>>q;
while(q--){
int x,y;
cin>>x>>y;
if(find(x)==find(y)) cout<<"Y\n";
else cout<<"N\n";
}
return 0;
}
cpp
#include<iostream>
#include<map>
#include<set>
using namespace std;
int f[1005], p[1005];
map<int, int> mp;
multiset<int, greater<int>> st;
int find(int x){
if(f[x]==x) return f[x];
return f[x]=find(f[x]);
}
void merge(int x, int y){
int a=find(x), b=find(y);
if(a!=b) f[b]=a;
}
int main(){
for(int i=0; i<1005; i++) f[i]=i;
char _;
int n, k, h;
cin >> n;
for(int i=1; i<=n; i++){
cin >> k >> _ >> p[i];
while(--k){
cin >> h;
merge(p[i], h);
}
}for(int i=1; i<=n; i++) mp[find(p[i])]++;
for(auto q:mp) st.insert(q.second);
cout << st.size() << "\n" << *st.begin();
st.erase(st.begin());
for(auto q:st) cout << ' ' << q;
cout << "\n";
}