#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAX=1010;
bool flag[MAX];
{
for(int i=1; i<=n; i++)
{
par[i]=i;
ranks[i]=0;
}
}
int find_set(int a){
if(a!=par[a]){
par[a]=find_set(par[a]);
}
return par[a];
}
void union_set(int a,int b){
a=find_set(a);
b=find_set(b);
if(ranks[a]>ranks[b])
par[b]=a;
else{
par[a]=b;
if(ranks[a]==ranks[b])
ranks[b]++;
}
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
make_set();
for(int i=1;i<=m;i++){
int a,b;
scanf("%d%d",&a,&b);
if(find_set(a)!=find_set(b))
union_set(a,b);
}
int ans=0;
memset(flag,0,sizeof(flag));///数组初始化
for(int i=1;i<=n;i++){
if(!flag[find_set(i)]){///元素i所在的集合为find_set(i),而并不是par[i];
ans++;
flag[find_set(i)]=true;
}
}
printf("%d\n",ans);
}
return 0;
}
#include <cstdio>
#include <cstring>
using namespace std;
const int MAX=1010;
bool flag[MAX];
int n,m;
///并查集核心代码
int par[MAX];
int ranks[MAX];
{
for(int i=1; i<=n; i++)
{
par[i]=i;
ranks[i]=0;
}
}
int find_set(int a){
if(a!=par[a]){
par[a]=find_set(par[a]);
}
return par[a];
}
void union_set(int a,int b){
a=find_set(a);
b=find_set(b);
if(ranks[a]>ranks[b])
par[b]=a;
else{
par[a]=b;
if(ranks[a]==ranks[b])
ranks[b]++;
}
}
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
make_set();
for(int i=1;i<=m;i++){
int a,b;
scanf("%d%d",&a,&b);
if(find_set(a)!=find_set(b))
union_set(a,b);
}
int ans=0;
memset(flag,0,sizeof(flag));///数组初始化
for(int i=1;i<=n;i++){
if(!flag[find_set(i)]){///元素i所在的集合为find_set(i),而并不是par[i];
ans++;
flag[find_set(i)]=true;
}
}
printf("%d\n",ans);
}
return 0;
}