用来解决连接问题
版本1:查找O(1),union O(N) (只有一层)
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
class unionfind{
int* id; //表示数据的组
int cnt;
public:
unionfind(int n)
{
id=new int[n];
for(int i=0;i<n;i++) //初始化时每个元素单独一组
{
id[i]=i;
}
cnt=n;
}
int myfind(int p)
{
return id[p];
}
bool isconnected(int p,int q)
{
return myfind(p)==myfind(q);
}
void myunion(int p,int q)
{
int id1=id[p];
int id2=id[q];
if(id1==id2)
{
return ;
}
for(int i=0;i<cnt;i++)
{
if(id[i]==p)
{
id[i]=q;
}
}
return ;
}
};
int main()
{
unionfind uf(100);
cout<<uf.isconnected(1,2)<<endl;
uf.myunion(1,2);
cout<<uf.isconnected(1,2)<<endl;
return 0;
}
版本2:union O(1) find O(N) (有很多层)
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
class unionfind{
int* parent; //表示数据的父节点
int cnt;
public:
unionfind(int n)
{
parent=new int[n];
for(int i=0;i<n;i++) //初始化时每个元素单独一组
{
parent[i]=i;
}
cnt=n;
}
int myfind(int p) //找根节点
{
while(p!=parent[p])
{
p=parent[p];
}
return p;
}
bool isconnected(int p,int q)
{
return myfind(p)==myfind(q); //根节点相同的话,是联通的
}
void myunion(int p,int q)
{
int root1=myfind(p);
int root2=myfind(q);
if(root1==root2)
{
return ;
}
parent[root1]=root2;
return ;
}
};
int main()
{
unionfind uf(100);
cout<<uf.isconnected(1,2)<<endl;
uf.myunion(1,2);
cout<<uf.isconnected(1,2)<<endl;
return 0;
}
版本3:基于size的优化
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
class unionfind{
int* parent; //表示数据的父节点
int* sz;
int cnt;
public:
unionfind(int n)
{
parent=new int[n];
sz=new int[n]; //以i为根的集合中元素个数
for(int i=0;i<n;i++) //初始化时每个元素单独一组
{
parent[i]=i;
sz[i]=1;
}
cnt=n;
}
int myfind(int p) //找根节点
{
while(p!=parent[p])
{
p=parent[p];
}
return p;
}
bool isconnected(int p,int q)
{
return myfind(p)==myfind(q); //根节点相同的话,是联通的
}
void myunion(int p,int q)
{
int root1=myfind(p);
int root2=myfind(q);
if(root1==root2)
{
return ;
}
else if(sz[root1]<sz[root2])
{
parent[root1]=root2;
sz[root2]+=sz[root1];
}
else
{
parent[root2]=root1;
sz[root1]+=sz[root2];
}
return ;
}
};
int main()
{
unionfind uf(100);
cout<<uf.isconnected(1,2)<<endl;
uf.myunion(1,2);
cout<<uf.isconnected(1,2)<<endl;
return 0;
}
版本4:基于rank的优化:
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
class unionfind{
int* parent; //表示数据的父节点
int* myrank;//以i为根的集合表示的树的层数
int cnt;
public:
unionfind(int n)
{
parent=new int[n];
myrank=new int[n];
for(int i=0;i<n;i++) //初始化时每个元素单独一组
{
parent[i]=i;
myrank[i]=1;
}
cnt=n;
}
int myfind(int p) //找根节点
{
while(p!=parent[p])
{
p=parent[p];
}
return p;
}
bool isconnected(int p,int q)
{
return myfind(p)==myfind(q); //根节点相同的话,是联通的
}
void myunion(int p,int q)
{
int root1=myfind(p);
int root2=myfind(q);
if(root1==root2)
{
return ;
}
else if(myrank[root1]<myrank[root2])
{
parent[root1]=root2;
++myrank[root2];
}
else
{
parent[root2]=root1;
++myrank[root1];
}
return ;
}
};
int main()
{
unionfind uf(100);
cout<<uf.isconnected(1,2)<<endl;
uf.myunion(1,2);
cout<<uf.isconnected(1,2)<<endl;
return 0;
}
前两个版本针对union进行优化,下面的版本针对find进行优化
版本5:路径压缩
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
class unionfind{
int* parent; //表示数据的父节点
int* myrank;//以i为根的集合表示的树的层数
int cnt;
public:
unionfind(int n)
{
parent=new int[n];
myrank=new int[n];
for(int i=0;i<n;i++) //初始化时每个元素单独一组
{
parent[i]=i;
myrank[i]=1;
}
cnt=n;
}
int myfind(int p) //找根节点
{
while(p!=parent[p])
{
parent[p]=parent[parent[p]]; //路径压缩 将p的父亲设置成p的父亲的父亲
p=parent[p];
}
return p;
}
bool isconnected(int p,int q)
{
return myfind(p)==myfind(q); //根节点相同的话,是联通的
}
void myunion(int p,int q)
{
int root1=myfind(p);
int root2=myfind(q);
if(root1==root2)
{
return ;
}
else if(myrank[root1]<myrank[root2])
{
parent[root1]=root2;
++myrank[root2];
}
else
{
parent[root2]=root1;
++myrank[root1];
}
return ;
}
};
int main()
{
unionfind uf(100);
cout<<uf.isconnected(1,2)<<endl;
uf.myunion(1,2);
cout<<uf.isconnected(1,2)<<endl;
return 0;
}
版本6:进一步路径压缩
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
class unionfind{
int* parent; //表示数据的父节点
int* myrank;//以i为根的集合表示的树的层数
int cnt;
public:
unionfind(int n)
{
parent=new int[n];
myrank=new int[n];
for(int i=0;i<n;i++) //初始化时每个元素单独一组
{
parent[i]=i;
myrank[i]=1;
}
cnt=n;
}
int myfind(int p) //找根节点
{
if(p!=parent[p])
{
parent[p]=myfind(parent[p]); //压缩成只有两层
}
return parent[p];
}
bool isconnected(int p,int q)
{
return myfind(p)==myfind(q); //根节点相同的话,是联通的
}
void myunion(int p,int q)
{
int root1=myfind(p);
int root2=myfind(q);
if(root1==root2)
{
return ;
}
else if(myrank[root1]<myrank[root2])
{
parent[root1]=root2;
++myrank[root2];
}
else
{
parent[root2]=root1;
++myrank[root1];
}
return ;
}
};
int main()
{
unionfind uf(100);
cout<<uf.isconnected(1,2)<<endl;
uf.myunion(1,2);
cout<<uf.isconnected(1,2)<<endl;
return 0;
}