union find(并查集)

在了解并查集之前我们需要了解一下动态连通性, 假设我们现在有10个点,1,2,3…,10。如果10个点相互独立,那么我们现在有10个连通分量。如果我们将1和2连接起来,那么我们现在就有9个连通分量了。现在假设我们不断地输入两个连通的点,怎么动态的求出这些点的连通分量呢?这就可以用到并查集这种数据结构了。
首先我们需要确定有多少个点,每个点属于哪个连通分量。在我们刚才提的问题中是属于比较简单的情况,我们使用数组就可以搞定了。union[i]表示第i个点属于第几个连通分量。
那么关于union find的代码如下:

#include <iostream>
#include <vector>
#include <utility>
using namespace std;

int unionCnt = 0;
vector<int> union10;

void makeUnion() {
    for (int i = 1;i <= 10;i++) {
        union10.push_back(i);
    }
    unionCnt = 10;
}
// 普通解法,时间复杂度是O(n)
int findUnion(int index) {
    return union10[index];
}

void connect(int node1, int node2) {
    int uId1 = findUnion(node1);
    int uId2 = findUnion(node2);
    for (int i = 0;i < union10.size();i++) {
        if (union10[i] == uId1) {
            union10[i] = uId2;
        }
    }
    unionCnt--;
}

int main() {
    makeUnion();
    connectQuick(1,3);
    connectQuick(2,3);
    connectQuick(5,8);
    cout << "union count is " << unionCnt << endl;
}

在上面代码的connect部分我们把node1所有的连通分量都变成了node2的。这无疑是很耗费时间的。如何改进呢?我们可以将一个连通分量看成是一个树,那么查找这个连通分量时查找根节点就可以了。
代码如下:

//quick union,时间复杂度是O(logn)
int findUnionQuick(int index) {
    while(index != union10[index - 1]) {
        index = union10[index - 1];
    }
    return index;
}

void connectQuick(int node1, int node2) {
    int uId1 = findUnionQuick(node1);
    int uId2 = findUnionQuick(node2);
    if (uId1 == uId2) {
        return;
    }
    union10[node1 - 1] = node2;
    unionCnt--;
    return;
}

ps:以前都是用csdn原来的那个编辑器的,现在用markdown编辑器看起来还挺好看的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值