目录:
并查集简介:
并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。这一类问题近几年来反复出现在信息学的国际国内赛题中。其特点是看似并不复杂,但数据量极大,若用正常的数据结构来描述的话,往往在空间上过大,计算机无法承受;即使在空间上勉强通过,运行的时间复杂度也极高,根本就不可能在比赛规定的运行时间(1~3秒)内计算出试题需要的结果,只能用并查集来描述。
并查集是一种树型的数据结构,用于处理一些不相交集合(disjoint sets)的合并及查询问题。常常在使用中以森林来表示。
-- -- 百度百科
简单来说:并查集是一种可以维护若干个不重叠的集合或无向图的连通块(也可以理解为一种集合)的数据结构。
给大家画一个并查集的简图,以便大家了解。
并查集的三种基本操作:
1、clean:将并查集进行初始化,其祖先是该元素本身。
· 2、find:查询一个元素属于哪个集合。
3、Merge:合并两个集合。
为了实现并查集,对于每一个集合,要确定集合唯一的表示方法。在并查集中,在每个集合中选取一个元素,代表整个集合,这个元素,就是集合的祖先。这样以来,我们只需要判断两个元素所在集合的代表元素是否相同,就可以判断其是否在一个集合内。
【代码实现】
int fa[100001];//记录元素的祖先
void clean()//初始化
{
for(int i=1;i<=n;i++)
{
fa[i]=i;
}
}
int find(int k)//寻找该元素的祖先
{
while(k!=fa[x])
{
x=fa[k];
}
return k;
}
void add(int x,int y)//合并两个集合
{
x=find(x);
y=find(y);
if(x!=y)
{
fa[x]=y;
}
}
优化并查集:
1、路径压缩:
所谓路径压缩就是在连接的时候把每一个子节点都连接到祖先节点上。
路径压缩运行速度较快,也是现阶段较为常用的优化方法,但路径压缩会改变树的形 态,不可以撤销操作或可持久化。
【代码实现】
int fa[100001];//记录元素的祖先
void clean()//初始化
{
for(int i=1;i<=n;i++)
{
fa[i]=i;
}
}
int find(int k)//寻找该元素的祖先
{
if(fa[k]==k)
{
return k;
}
return fa[k]=find(fa[k]);
}
void add(int x,int y)//合并两个集合
{
x=find(x);
y=find(y);
if(x!=y)
{
fa[x]=y;
}
}
2、按秩合并 :
所谓按序合并就是记录连接中两个树的高度,由低的连接到高的上,通常也可以记录 树 的大小。
按秩合并的运行速度略慢与路径压缩,但是按秩合并不会改变树的形状态,多用于可撤 销并查集和可持久化并查集中。
【代码实现】
int fa[1000001];//记录祖先元素
int h[1000001];//记录深度
void clean(int n)//初始化
{
for (int i=0;i<=n;i++)
{
fa[i]=i;
rank[i]=0;
}
}
int find(int k)//查找该元素的祖先
{
if(fa[k]==k)
{