1.定义
并查集是一种处理不相交可合并集合关系的数据结构,具有查询,合并2种基本操作;
2.实现
a.数组模拟
例
洛谷 P1551 亲戚
题目描述
规定:x 和 y 是亲戚,y 和 z 是亲戚,那么 x 和 z 也是亲戚。如果 x,y 是亲戚,那么 x 的亲戚都是 y 的亲戚,y 的亲戚也都是 x 的亲戚。
输入格式
第一行:三个整数 n,m,p,(n,m,p≤5000),分别表示有 n 个人,m 个亲戚关系,询问 p 对亲戚关系。
以下 、m 行:每行两个数Mi,Mj,1≤Mi, Mj≤N,表示 Mi 和 Mj 具有亲戚关系。
接下来p 行:每行两个数 Pi,Pj,询问 Pi 和 Pj 是否具有亲戚关系。
输出格式
p 行,每行一个 Yes 或 No。表示第 个询问的答案为“具有”或“不具有”亲戚关系。
输入输出样例
输入
6 5 3
1 2
1 5
3 4
5 2
1 3
1 4
2 3
5 6
输出
Yes
Yes
No
代码如下;
#include<iostream>
using namespace std;
int fa[5500],n,m,p;//fa[] 作为一队亲戚的代表
int find (int z){
if(z==fa[z])return z;//z为代表
else if(fa[z]==0)return z; //z没有代表
else find(fa[z]);//z不是代表,递归寻找z的代表的代表
}
int main(){
int x,y;
cin>>n>>m>>p;
for(int i=0;i<m;i++){
cin>>x>>y;
if(fa[x]!=0){
fa[find(x)]=find(x);//更新代表
}else{
fa[x]=find(x);
}
if(fa[y]!=0){
fa[find(y)]=find(x);
}
else {
fa[y]=find(x);//更新代表
}
}
for(int i=0;i<p;i++){
cin>>x>>y;
if(find(x)==find(y)){
cout<<"Yes"<<endl;
}else{
cout<<"No"<<endl;
}
}
return 0;
}
b.头文件
set(本质是一种红黑树(一种比较优秀的平衡二叉树))集合的头文件是<set>,有以下几种操作;
set<int> ds:建立一个名为ds,元素类型为int的集合;
ds.insert(x):在集合中插入元素x,若该元素已存在,则不进行任何操作;
ds.erase(x):在集合中删除元素x,若该元素不存在,则不进行任何操作;
ds.erase(it):删除集合中地址为it的元素;
ds.end():返回集合中最后一个元素的下一个元素的·地址;
ds.find(x):查询x在集合,如果不存在,则返回ds.end();
ds.lower_bound(x):查询不小于x的最小的数的地址,如果不存在,则返回ds.end();
ds.upper_bound(x):查询大于x的最小的数的地址,如果不存在,则返回ds.end();
ds.empty():如果集合是空,则返回1,否则返回0;
ds.size():返回集合中元素的个数