跳到主要内容

并查集

并查集是一种树型的数据结构,用于处理一些不相交集合的合并查询问题。在使用中常常以森林来表示。

并查集支持操作:

1、将两个集合合并

2、询问两个元素是否在一个集合当中

思路

每个集合用一棵树来表示,以根节点编号表示整个集合,每个节点存储父节点p[x]

判断树根 if(p[x]==x)

求集合编号 while(p[x]!=x) x=p[x];

合并集合:x和y,x→根节点x,p[x]=y。

朴素并查集

int p[N]; //存储每个点的祖宗节点
// 返回x的祖宗节点
int find(int x)
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}

// 初始化,假定节点编号是1~n
for (int i = 1; i <= n; i ++ ) p[i] = i;

// 合并a和b所在的两个集合:
p[find(a)] = find(b);

维护size的并查集

int p[N], size[N];
//p[]存储每个点的祖宗节点, size[]只有祖宗节点的有意义,表示祖宗节点所在集合中的点的数量
// 返回x的祖宗节点
int find(int x)
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
// 初始化,假定节点编号是1~n
for (int i = 1; i <= n; i ++ )
{
p[i] = i;
size[i] = 1; // 初始化size
}

// 合并a和b所在的两个集合:
size[find(b)] += size[find(a)]; // 先更新size,再合并
p[find(a)] = find(b);

维护到祖宗节点距离的并查集

int p[N], d[N];
//p[]存储每个点的祖宗节点, d[x]存储x到p[x]的距离
// 返回x的祖宗节点
int find(int x)
{
if (p[x] != x)
{
int u = find(p[x]);
d[x] += d[p[x]];
p[x] = u;
}
return p[x];
}

// 初始化,假定节点编号是1~n
for (int i = 1; i <= n; i ++ )
{
p[i] = i;
d[i] = 0;
}

// 合并a和b所在的两个集合:
p[find(a)] = find(b);
d[find(a)] = distance; // 根据具体问题,初始化find(a)的偏移量