用并查集求连通块
进行了路径压缩,用t数组来标记联通块的个数(find函数是用来查找是否连通的)
记得一定要经pre[]数组初始化。
代码:
#include <iostream>
#include <string.h>
using namespace std;
#define MAX 1005
int pre[MAX];
int T;
int N,M;
int find(int x)
{
int r=x;
while(pre[r]!=r)
{
r=pre[r];
}
int i=x,j;
while(i!=r)
{
j=pre[i]; // 在改变上级之前用临时变量 j 记录下他的值
pre[i]=r;//把上级改为根节点
i=j;
}
return r;
}
void Union(int x,int y)
{
int fx=find(x);
int fy=find(y);
if(fx!=fy)
pre[fy]=fx;
}
int main()
{
int x,y;
int t[MAX];
cin>>T;
while(T--)
{
cin>>N>>M;
for(int i=1;i<=N;i++)//务必记住并查集先初始化;
pre[i]=i;
for(int i=1;i<=M;i++)
{
cin>>x>>y;
Union(x,y);
}
memset(t,0,sizeof(t));
for(int i=1;i<=N;i++)
t[find(i)]=1;//经所有的联通块标记,之后按照标记统计个数。如果多个数字构成一个联通块,
int ans=0;
for(int i=1;i<=N;i++)
if(t[i])ans++;
cout<<ans<<endl;
}
return 0;
}