并查集

并查集的精髓是将每两个点联系起来,将它们的祖先进行储存,最后判断有几个部分。

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
using namespace std;
inline int read()
{
    int x=0,f=1;
    char ch;
    do
    {
        ch=getchar();
        if(ch=='-') f=-1;
    }while(ch<'0'||ch>'9');
    do
    {
        x=x*10+(ch-'0');
        ch=getchar();
    }while(ch>='0'&&ch<='0');
    return x*f;
}
int f[10000];
int getf(int v)//寻找他们的祖先 
{
    if(f[v]==v) return v;//自己是自己的祖先 
    else
    {
        f[v]=getf(f[v]);//找自己祖先的祖先 
        return f[v];
    }
}
int main()
{
    int n,m;
    n=read();
    m=read();
    int i,j,k;
    for(i=1;i<=n;i++) f[i]=i;//没有联系之前,每个点的祖先都是自己 
    for(i=1;i<=m;i++)
    {
        int x,y;
        x=read();
        y=read();
        int h1,h2;
        h1=getf(x);//寻找他们的祖先 
        h2=getf(y);
        if(h1!=h2)//如果不是一个部分中的,就合并 
        {
            f[h2]=h1;//一定是h2而不是x,不然找祖先就会有分叉,一个点有多个祖先 
        }
    }
    int ans=0;
    for(i=1;i<=n;i++) if(f[i]==i) ans++;//如果一个点的祖先是自己,他就是一个部分,因为一个部分只会有一个最远的祖先 
    printf("%d",ans);
    return 0;
}

最后祝大家编程顺利。

蒟蒻总是更懂你✿✿ヽ(°▽°)ノ✿
原文地址:https://www.cnblogs.com/WWHHTT/p/7833781.html