并查集

并查集的算法应用

  • 欧拉回路中判断图是否联通
  • 最小生成树克鲁斯卡算法—Kruskal算法

并查集模板

并查集可以实现两个,查找与合并
并查集是一个树的结果,总的还说是森林
可以判断两个结点是否在一个图中,或一个图是否连通
或者实现找朋友题,朋友可以传递,判断谁和谁是否是朋友
房间是否连接
是否为亲戚

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int fa[10005];
int father(int x){
    if(fa[x]==x)return x;
    return fa[x]=father(fa[x]);//动态规划策略,直接
}
void unionn(int x,int y){
    fa[father(y)]=father(x);
}
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            fa[i]=i;
        }
        for(int i=0;i<m;i++){
            int z,x,y;
            scanf("%d%d%d",&z,&x,&y);

            if(z==1){
                unionn(x,y);
            }else if(z==2){
                printf("%s\n",father(x)==father(y)?"Y":"N");
            }
        }


    return 0;
}

例题:

HUD1232畅通工程

http://acm.hdu.edu.cn/showproblem.php?pid=1232

在最后结果中,一棵树上的结点的根结点不一定相同,但是,题目的根结点总会一棵树上
判断有几棵树的方法是,判断根是否为本身序号,因为根的根结点就是本身

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int fa[1005];

int father(int x){
    if(fa[x]==x)return x;
    return fa[x]=father(fa[x]);//动态规划策略,直接
}
void unionn(int x,int y){
    fa[father(y)]=father(x);
}
int main(){
    int n,m;
    while(scanf("%d",&n)!=EOF&&n){
        scanf("%d",&m);
        for(int i=0;i<=n;i++)fa[i]=i;


        for(int i=0;i<m;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            unionn(a,b);
        }
        int sum=0;
        for(int i=1;i<=n;i++){
            if(fa[i]==i)sum++;
        }

        printf("%d\n",sum-1);
    }
}

HUD How Many Tables

http://acm.hdu.edu.cn/showproblem.php?pid=1213

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int fa[1005];

int father(int x){
    if(fa[x]==x)return x;
    return fa[x]=father(fa[x]);//动态规划策略,直接
}
void unionn(int x,int y){
    fa[father(y)]=father(x);
}
int main(){
    int t;
    cin>>t;
    while(t--){
        int n,m;

        scanf("%d%d",&n,&m);

        for(int i=0;i<=n;i++)fa[i]=i;


        for(int i=0;i<m;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            unionn(a,b);
        }


        int sum=0;
        for(int i=1;i<=n;i++){
            if(fa[i]==i)sum++;
        }

        printf("%d\n",sum);
    }

    return 0;
}

转载于:https://www.cnblogs.com/Emcikem/p/11342206.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值