并查集
并查集的主要思想就是查找两个子节点的父亲节点是否是同一个,和把两个父亲节点的集合合成一个。
并查集的路径压缩:大概思想就是把一棵树上的所有子节点(和根节点直接相连的,没有和根节点直接相连的)全部都直接连在根节点上。并查集算法主要就是查找父亲节点,所以有些路径本来就没有什么必要,压缩掉也没关系
#include <iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#include<stack>
#include<vector>
#include<queue>
#include<map>
#define INF 0x3fffffff
#define me(a,b) memset(a,b,sizeof(a))
#define X 200907
#define mod 10000
typedef long long ll;
const int maxn=1e3+10;
using namespace std;
int vis[maxn],mp[maxn][maxn],fa[maxn];
using namespace std;
int n,m,x,y;
int findfather(int a)//用递归实现
{
if(fa[a]==a)
return a;
else
{
fa[a]=findfather(fa[a]);
return fa[a];
}
}
/*int findfather(int a)//用递推实现
{
while(a!=fa[a])//不是根节点就继续循环直到找到根节点
{
a=fa[a];
}
return a;
}*/
void unionn(int x,int y)
{
int tx=findfather(x);
int ty=findfather(y);
if(tx!=ty)//父亲节点不同
fa[tx]=ty;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)//初值赋为所有节点的根节点都是它自己
fa[i]=i;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
unionn(x,y);
}
int ans=0;
for(int i=1;i<=n;i++)
{
if(fa[i]==i)//有多少个父亲节点等于它本身,就有几个集合
ans++;
}
printf("%d\n",ans);
}
return 0;
}