并查集本质是通过一个一维数组来维护一个森林。
开始时森林中的每一个节点都是孤立的,各自形成一个树。
之后进行若干次合并操作,每次合并将两个树合并为一个更大的树。
初始化
const int N = INT_MAX;
int pre[N]; //记录每个节点的前驱节点
int rank[N]; //记录节点高度
void init(int n)
{
for(int i=0;i<n;i++)
{
pre[i] = i;
rank[i] = 1;
}
}
查找(find)
查询两个元素是否属于同一集合
find(int x)
{
if(pre[x] != x)
return find(pre[x]);
return x; //当 pre[x]=x 时,即为根节点
}
//优化:在查询的同时,将当前节点的上级修改为根节点
int find(int x)
{
if(pre[x] == x)
return x;
return pre[x] = find(pre[x]);
}
合并(union)
将两个不相交的集合合并成一个集合
bool join(int x, int y)
{
int fx = find(x);
int fy = find(y);
if(fx == fy) return false; //x,y属于同一集合,不需要合并
if(rank[fx] > rank[fy])
pre[fy] =fx; //fx作为fy上级
else{
if(fy == fx) rank[fy]++;
pre[fx] = fy; //fy作为fx上级
}
return true; //合并成功
}