并查集:
作用于:一个不相交集
效果:在近于常数的时间内完成:1.确定一个元素所在的集合,2.合并两集合。
思路:在每个集合中,令一个元素表示这个集合,称这个元素为:代表元 。使用一颗树代表一个集合,故代表元为这颗树的根。
节点上有双亲指针,代表元的双亲指针指向自己。
查找操作:对于一个节点,顺着双亲指针向上,则根为代表元。
合并操作:把一棵树的根的双亲指针指向另一颗树的根。为了使树合并后不产生退化,让深度浅的那棵指向深的那颗。
路径压缩:把从根到某一节点的路径上的所有节点的双亲指针指向根节点。
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6;
int parent[maxn],ranc[maxn];
int serc(int pos)
{
while(parent[pos]!=pos)
{
pos=parent[pos];
}
return pos;
}
void init(int siz)
{
for(int i=0;i<siz;i++)
{
parent[i]=i;
ranc[i]=1;
}
}
void merg(int x,int y)
{
x=serc(x);
y=serc(y);
if(ranc[x]<ranc[y])
parent[x]=parent[y];
else
{
if(ranc[x]==ranc[y])ranc[x]++;
parent[y]=parent[x];
}
}
void compress(int pos)
{
int tpos=serc(pos);
int cur;
while(parent[pos]!=pos)
{
cur=parent[pos];
parent[pos]=tpos;
pos=cur;
}
}
int main()
{
int siz,curx,cury;
cin>>siz;
init(siz);
while(cin>>curx>>cury,curx!=-1)
{
merg(curx,cury);
}
for(int i=0;i<siz;i++)
{
// compress(i);
cout<<parent[i]<<" ";
}
return 0;
}