并查集的实现(复杂度:比O(log(n))还要快的阿克曼函数的反函数的数量级,接近于O(1))
编号代表每个元素,数组par表示的是父亲的编号,par[x]=x时,x是所在的树的根
int par[MAX_N];///父亲
int high[MAX_N];///树的高度
///初始化n个元素
void init(int n)
{
for(int i=0; i<n; i++)
{
par[i]=i;
high[i]=0;
}
}
///查询树的根(递归写法)
int Find(int x)
{
return (par[x]==x)?x:Find(par[x]);
}
///非递归写法
int Find(int x)
{
int r=x;
while(r!=par[r]) ///找根r
r=par[r];
int t=x;
while(t!=r) ///将x到r路径上的点的父节点均置为根r
{
int m=par[t];
par[t]=r;
r=m;
}
return r;
}
///合并x和y所属的集合
void unite(int x,int y)
{
x=Find(x);
y=Find(y);
if(x==y) return ;
if(high[x]<high[y]) par[x]=y;
else
{
par[y]=x;
if(high[x]==high[y]) high[x]++;
}
}
///判断x和y是否属于同一个集合
bool same(int x,int y)
{
return Find(x)==Find(y);
}