CSP-普适结构–并查集
知识简述
并查集是一种图论中十分常见的数据结构,在联通模块和生成树问题中具有十分重要的作用,因此并查集是在程序设计中必须掌握的知识模块。
正如其名,并查集结构主要关注两个方面:
1、并操作
2、查操作
要组织这种结构,可以使用各种各样的数据结构:数组、链表或者是树都可以做到。但是考虑到在比赛时的实现简易度,使用数组比较方便易行。
在对节点组进行并和查操作时,找出他得所有同组节点是不容易的,且可能会耗费掉巨大的时间复杂度,因此我们换一种思路:将一个元素作为每个组别的代表,在进行并查时只需要使用代表元素进行操作即可。为了减少空间开销,我们可以将整个并查集组织成下图的结构:
每个组别使用祖先父亲节点作为这个点的代表元素,使用一个par[]数组来指示每个点的祖先即可。
考虑3种组织操作操作:
初始化:
在没有进行并之前,每个节点是独立的,其同组节点只有自己,因此可以直接将每个点的祖先置为自己,初始化状态:
查操作:
在查询一个节点的所属组别是,只需要查询出其祖先父亲节点就可以完成对组别的标识,进而进行后续操作,查操作的示例图:
并操作:在进行并操作时,关键的是如何组织两个结构类型的根节点,这决定了整个并查集的性能(如果并查集的高度过大,同层的元素较少会导致性能退化)
因此我们使用点数优先的路径压缩法:(想了解各种路径压缩优化方法的同学可以百度)
在试行并操作时遵从两个操作原则:
1、将节点数较少的集合并入到节点数较少的集合中。
2、并入时直接将“小集合”祖先节点连接到“大集合”祖先节点的孩子节点即可。
操作图例如下:
具体实现源码(c++):
const int max_floor=3e4;
int parent[max_floor];
int number[max_floor];
int find(int pos)
{
if(parent[pos]==pos)
return pos;
else
return find(parent[pos]);
}
void