并查集(学习)

并查集是一种数据结构,可以快速合并多个集合,查询元素是否在相同集合中,维护”朋友的朋友是朋友“这样一种关系

操作一,初始化并查集,就是将各个节点的父亲节点初始化为自己:

for (int i = 1; i <= n; i ++) {
    father[i] = i;
}

操作二,给出元素x,询问这个元素所在树的根节点:

int root(int x) {
    if(x == father[x]) {
        return x;
    }
    else {
        return root(father[x]); //递归查找父亲节点的父亲
    }
}

操作三,给两个元素,将两个元素所在集合合并:
即把一个树的树根连接在另一棵树的树根上,前提要保证这两个集合互不相关~

int rx = root(x), ry = root(y); //找到x和y的根节点
if(rx != ry) { //保证两个树的树根不相同,表示不是同一个集合
    father[rx] = ry; //其中一个根认另一个根做父亲,两个树有了一个共同的父亲节点,两个集合就变成一个集合
}

上述查,并一次时间复杂度均为O(1)


并查集的优化:

一、路径压缩:将所有元素直接连到根节点上

int root(int x) {
    if(x == father[x]) {
        return x; //这个元素已经直接连接到根节点上了,返回根的值
    }
    else {
        return father[x] = root(father[x]); //这个元素的父亲节点不是根,递归查找这个元素父节点的父节点,直到找到根节点,建立连接
    }
}

二、按秩合并:合并过程中避免长链。
保存每个树的高度,在合并过程中,让较高树的祖先作为新的祖先,尽量防止树的高度变大。

以上两种优化方法,任一种都可以让单次操作 均摊时间复杂度变成O(n * log(n))
同时使用两种优化,单次操作均摊时间复杂度可以降至O(α(n)),α为反阿克曼函数。


并查集的分类:
二分图染色,
拆点并查集,
种类并查集(又叫加权并查集,有异或运算,是一种重要的并查集,维护”敌人的敌人是朋友“这样一种重要关系)

种类并查集查找根节点模板:

int find(int x) {
    if(x == p[x]) {
        return x;
    }
    int t = p[x];
    p[x] = find(p[x]);
    d[x] = d[t] ^ d[x];
    return p[x];
}

种类并查集合并集合,模板:

int pa = find(a), int pb = find(b);
if(pa != pb) {
    p[pb] = pa;
    d[pb] = d[a] ^ d[b] ^ 1;
}

“进阶算法”专栏(目录)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值