关于并查集问题(只谈我的个人理解)

以前学最小生成树的时候,就一直听并查集的大名,就是一直没去看,所以最小生成树也没搞明白。

等接触到并查集之后才知道,用来是这一类问题啊。(纯属吐槽)

并查集是用来判断图的连通性的一种算法。

并查集是一种已知叶寻找根的一种算法,大概分为两个部分,前面一个我叫他寻根,后一个我叫他并集。

初始化数组:

    for(int i=0;i<n;i++)//n表示输入的结点的个数
        pho[i]=i;//将每一个结点的前导点设置为自己

寻根函数:

int find(int r)
{
    while(r != pho[r])
        r = pho[r];
    return r;
}

并集函数:

void join(int x,int y)
{
    int fx = find(x),fy = find(y);
    if(fx != fy) pho[fx] = fy;
}

但是如果采取这种寻根操作的话,很显然,树的层数会很大。

很显然树的层数越大,对于该树的遍历就会越麻烦,所以我们可以采取路径压缩。

int better_find(int r)
{
    int x = r;
    while(r != pho[r])
        r = pho[r];
    int i = x,j;
    while(i != r){
        j = pho[i];
        pho[i] = r;
        i = j;
    }
    return r;
}

很显然,通过压缩之后,我们的树就只有两层,对于后面的计算是相当方便的。

上一波完整代码。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double dl;
const int N = 1e6 + 7;
int pho[N];
int relation[N][2];
int find(int r)
{
    int x = r;
    while(r != pho[r])
        r = pho[r];
    int i = x,j;
    while(i != r){
        j = pho[i];
        pho[i] = r;
        i = j;
    }
    return r;
}
void join(int x,int y)
{
    int fx = find(x),fy = find(y);
    if(fx != fy) pho[fx] = fy;
}
int main()
{
    int n,m,p,k;
    cin >> n >> m;
    for(int i = 1;i <= n;++i)
        pho[i] = i;
    for(int i = 1;i <= m;++i)
        cin >> relation[i][0] >> relation[i][1];
    for(int i = 1;i <= m;++i)
        join(relation[i][0],relation[i][1]);
    int t;
    cin >> t;
    while(t--){
        cin >> p >> k;
        int a = find(p),b = find(k);
        a == b ? cout << "Yes" <<endl : cout << "No" << endl;
    }
    return 0;
}

这个代码的作用是已知10个节点,给出m组关系,求给t组数据是否连通


猜你喜欢

转载自blog.csdn.net/qq_41791981/article/details/80504363