集合(并查集)

1.定义

并查集是一种处理不相交可合并集合关系的数据结构,具有查询,合并2种基本操作;

2.实现

a.数组模拟

洛谷 P1551 亲戚

题目描述

规定:xy 是亲戚,yz 是亲戚,那么 xz 也是亲戚。如果 xy 是亲戚,那么 x 的亲戚都是 y 的亲戚,y 的亲戚也都是 x 的亲戚。

输入格式

第一行:三个整数 n,m,p,(n,m,p≤5000),分别表示有 n 个人,m 个亲戚关系,询问 p 对亲戚关系。

以下 、m 行:每行两个数MiMj,1≤Mi, MjN,表示 MiMj 具有亲戚关系。

接下来p 行:每行两个数 Pi,Pj,询问 PiPj 是否具有亲戚关系。

输出格式

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>,有以下几种操作;

  1. set<int> ds:建立一个名为ds,元素类型为int的集合;

  1. ds.insert(x):在集合中插入元素x,若该元素已存在,则不进行任何操作;

  1. ds.erase(x):在集合中删除元素x,若该元素不存在,则不进行任何操作;

  1. ds.erase(it):删除集合中地址为it的元素;

  1. ds.end():返回集合中最后一个元素的下一个元素的·地址;

  1. ds.find(x):查询x在集合,如果不存在,则返回ds.end();

  1. ds.lower_bound(x):查询不小于x的最小的数的地址,如果不存在,则返回ds.end();

  1. ds.upper_bound(x):查询大于x的最小的数的地址,如果不存在,则返回ds.end();

  1. ds.empty():如果集合是空,则返回1,否则返回0;

  1. ds.size():返回集合中元素的个数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值