并查集 & 最小生成树

并查集 Disjoint Sets

什么是并查集

简单来说,并查集的主要操作有:

   1- 合并两个不相交的集合
   2- 查询两个元素是否属于同一个集合

老样子,先上引例——

    从题目中我们可以得到一些提示,它就是要让我们构建一个关系集合出来,再快速查找两个元素是否位于同一集合,这显然就与并查集的效用十分吻合。

合并的过程是怎样的(图示)?

并查集的工作原理

下面给出并查集的核心函数:

查询同时路径压缩
int GetFather(int v) {  //查询元素v所在集合的根节点
    if (Father[v] == v)return v;    //v本身为根
    else {
        Father[v] = GetFather(Father[v]);   //只对v到根这条路径上的节点进行路径压缩
        return Father[v];
    }
}  
合并两个集合
void Merge(int x, int y) {  //合并元素x和元素y所在集合
    int fx, fy;
    fx = GetFather(x);  //先找出x和y所在集合的根
    fy = GetFather(y);  //两根不相同,说明x和y位于不同集合
    if (fx != fy)Father[fx] = fy;   //将fy设为fx的父亲,合并两个集合
}  

我们回到引例,我们现在可以很轻松地解决此题(伪代码)——

for (i = 1; i <= n; ++ i)Father[i] = i; //初始化
for (i = 1; i <= m; ++ i) { //读入关系
    cin >> x >> y;
    Merge(x, y);
}
for (i = 1; i <= q; ++ i) { //回答询问
    cin >> x >> y;
    if (GetFather(x) == GetFather(y))
        cout << "Yes";
    else cout << "No";
}  (O(m))

提供几道并查集的简单练习:

NKOJ 3197 岛屿
NKOJ 1046 关押罪犯

###并查集的启发式合并(有缘再补)

最小生成树 Minnimum Spanning Tree(MST)

什么是最小生成树

简言之,最小生成树就是在一个连通图中生成一棵树,刚好连通所有节点,所含边数(或边权总和最小)。

01-23 01:00