算法之并查集

并查集(Union-find Data Structure)是一种树型的数据结构。它的特点是由子结点找到父亲结点,用于处理一些不交集(Disjoint Sets)的合并及查询问题。

  • Find:确定元素属于哪一个子集。它可以被用来确定两个元素是否属于同一子集。
  • Union:将两个子集合并成同一个集合

关于并查集是什么我们在这里不作详细讲解,我们直接学习其中操作,如果你对并查集不了解,请自行去查找

一.合并:

我们将两个集合合并在一起模版:

//并查集:
const int N = 1e3;
int fa[N], sz[N], dep[N];
int findset(int x)
{
	if (x == fa[x])
		return x;
	else
		return findset(fa[x]);
}
void Union(int x, int y)
{
	int fx = findset(x), fy =findset(y);
	if (fx == fy)
		return;
	else
		fa[fx] = fy;//我们这里默认将fx合并到fy
}

二.路径压缩:

我们可以将一个长链压缩成右图:

好处:可以大大减少合并次数

模版:

//路径压缩;
int findset(int x)
{
	if (fa[x] == x)
		return x;
	fa[x] = findset(fa[x]);
	return fa[x];
}
//简写
int findset2(int x)
{
	return x == fa[x] ? x : (fa[x] == findset2(fa[x]));
}

三.按size合并

模版:

const int N = 1e3;
int fa[N], sz[N], dep[N];
//启发式合并;
//size合并;
void Union(int x, int y)
{
	int fx = fa[x], fy = fa[y];
	if (fx == fy)
		return;
	if (sz[fx] > sz[fy])//默认是将fx合并到fy,所以我们如果size:fx>fy,可以交换fx fy,这样和默认就一样了
		swap(fx, fy);
	fa[fx] = fy;//默认是将fx合并到fy
	sz[fy] += sz[fx];//fx合并到fy后,fy上元素个数会增加sz[fx]个
}

四.按深度合并:

//按深度合并
void Union(int x, int y)
{
	int fx = fa[x], fy = fa[y];
	if (fx == fy)
		return;
	if (dep[fx] > dep[fy])
		swap(fx, fy);
	fa[fx] = fy;
	if (dep[fx] == dep[fy])//注意:只有两个深度相同时,合并总深度才会增大
		dep[fy]++;
}

以上就是我们关于并查集的模版

你学会了吗?现在通过这题来测试下吧:

【模板】并查集 - 洛谷

我的解答:

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m,z,x,y;
int fa[N];

int findset(int x)
{
    if(fa[x]==x)
    return x;
    fa[x]=findset(fa[x]);
    return fa[x];
}

int main()
{
    //取消同步流
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    //输入
    cin>>n>>m;
    //构造并查集
    for(int i=1;i<=n;i++)
    {
        fa[i]=i;
    }
    for(int i=1;i<=m;i++)
    {
        cin>>z>>x>>y;
        if(z==1)//合并操作
        {
            int fx=findset(x),fy=findset(y);
            if(fx==fy)
                continue;
            else
                fa[fx]=fy;
        }
        else//查询操作
        {
            int fx=findset(x),fy=findset(y);
            if(fx==fy)
                cout<<'Y'<<endl;
            else
                cout<<'N'<<endl;
        }
    }
    return 0;
    
}

下面给一道练习题:

亲戚 - 洛谷

#include <bits/stdc++.h>
using namespace std;
const int N=1e4;
int a[N];

int findset(int x)
{
    if(a[x]==x)
        return x;
    a[x]=findset(a[x]);
    return a[x];
}


int main()
{
    int n,m,p;
    scanf("%d%d%d",&n,&m,&p);
    for(int i=1;i<=n;i++)
        a[i]=i;
    for(int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        //并查集
        int fx=findset(x),fy=findset(y);
        if(fx==fy)
            continue;
        else
            a[fx]=fy;
    }
    for(int i=1;i<=p;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        //并查集
        int fx=findset(x),fy=findset(y);
        if(fx==fy)
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}

最后,感谢大家的支持!!!

相关推荐

  1. 算法实现

    2024-03-29 21:42:06       34 阅读
  2. 【数据结构】算法总结

    2024-03-29 21:42:06       42 阅读
  3. C语言-算法-

    2024-03-29 21:42:06       32 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-29 21:42:06       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-29 21:42:06       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-29 21:42:06       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-29 21:42:06       18 阅读

热门阅读

  1. 数据关联_3.7

    2024-03-29 21:42:06       16 阅读
  2. 基于Python的高考志愿辅助填报系统

    2024-03-29 21:42:06       15 阅读
  3. Spring

    Spring

    2024-03-29 21:42:06      21 阅读
  4. dockerfile编写

    2024-03-29 21:42:06       16 阅读
  5. 008_function_convention_in_Matlab中的函数约定

    2024-03-29 21:42:06       15 阅读
  6. linux三剑客之grep

    2024-03-29 21:42:06       21 阅读
  7. mysql5.7安装

    2024-03-29 21:42:06       16 阅读
  8. LeetCode 704 二分查找

    2024-03-29 21:42:06       18 阅读