并查集的精髓是将每两个点联系起来,将它们的祖先进行储存,最后判断有几个部分。
#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; }
最后祝大家编程顺利。