Disjoint Set, 互质集合

Disjoint Set,(一个元素不同时属于多个集合)。这里用森林结构代表集合集,树代表集合,根元素为代表元素   用rank数组记录数高。

FIndSet(x)  求包含元素晓得集合的代表元素,

在树中,查找x,后返回代表元素,同时压缩路径,将x,到根的所有节点指向根节点。降低搜索时间。

unite(x,y) 将树x,y合并。

将树高度低的加到树高的集合,使高度低的集合根节点指向高度高的根节点。

#include<iostream>
#include<vector>
using namespace std;
class DisjointSet{                                                             //森林结构
public:
vector<int> rank,p;
DisjointSet() {}                                                //构造方法
DisjointSet(int size) {
rank.resize(size,0);
p.resize(size,0);
for (int i=0;i<size;i++) makeSet(i);            //建立树
}
void makeSet(int x) {
p[x]=x;
rank[x]=0;
}
bool same(int x,int y) {
return findSet(x)==findSet(y);
}
void unite(int x,int y) {
link(findSet(x),findSet(y));                            
}
void link(int x,int y) {
if (rank[x]>rank[y]) {                        //这里用数组下表表示节点即元素,数组里的数为代表元素
p[y]=x;
}
else {
p[x]=y;
if (rank[x]==rank[y]) {
rank[y]++;
}
}
}
int findSet(int x) {
if (x!=p[x]) {                                       //高度为零时,代表元素即元素
p[x]=findSet(p[x]);                        //p[x],即为代表元素的下标?
}
return p[x];
}
};
int main() {
int n,a,b,q;
int t;
cin>>n>>q;
DisjointSet ds=DisjointSet(n);
for (int i=0;i<q;i++) {
cin>>t>>a>>b;
if (t==0) ds.unite(a,b);
else if (t==1) {
if (ds.same(a,b)) cout <<1<<endl;
else cout<<0<<endl;
}
}
return 0;
}

猜你喜欢

转载自blog.csdn.net/acm160920007/article/details/76911977