【算法】【并查集】并查集
并查集
-
将两个集合合并;
-
询问两个元素是否在一个集合当中;
-
基本原理:每个集合用一颗树来维护,每个集合根节点的编号是当前集合的编号,每个节点存储它的父节点,p[x] 表示x的父节点;
-
如何判断树根:
-
p[x] = x;
-
-
查找:如何求x的集合编号:
- 想判断某个点属于哪个集合,找到它所在的树的树根;
while(p[x] != x) x = p[x];
- 路径压缩(优化)
第一次遍历,将遍历的这条链上的节点都指向根节点;
- 想判断某个点属于哪个集合,找到它所在的树的树根;
-
合并:如何合并两个集合:
- p[x]是x的集合编号,p[y]是y的集合编号;令p[x] = y;
实现
最重要的两个操作,合并和查找;难点在于如何将问题抽象出来,同时merge函数会根据具体问题细微的修改;
还有一步比较关键,就是初始化集合,初始化的时候每个节点的parent都指向该节点;
vector<int> parent;
void init(int n)
{
for(int i = 0; i < n; i++)
parent.push_back(i);
}
int find(int x)
{
int root = x;
while(parent[root] != root)
root = parent[root];
return root;
}
int merge(int a, int b)
{
int p_a = find(a);
int p_b = find(b);
if(p_a != p_b)
parent[p_a] = p_b;
return p_a != p_b;
}
知识的价值不在于占有,而在于使用