Description
小李今天请客吃饭,小李把认识的人都请了。准备定桌子的时候,小李突然想起来,他的某些朋友是互相连面都没见过的,为了照顾这些朋友不让他们和陌生人同桌,小李决定多订几张桌子,只让互相认识的人坐一桌。但是小李的朋友们很体谅他,说如果他们之间有共同的朋友,那他们也能勉强坐在一桌。
例如:
1.如果A认识B, B认识C,那A, B, C就可以坐一桌
2.但是如果A认识B, B认识C, D认识E,那么A、B、C可以坐在一起,而D和E就得坐另一张桌子一起吃饭
请你帮小李算算他最少要定多少张桌子才合适。
Input
第一行输入一个整数T(1<=T<=25),表示测试用例的数量
接下来是两个整数N和M(1<=N,M<=1000),N表示朋友的数量,朋友从1标记到N
之后的M行,每一行由两个整数A和B(A!=B)组成,这意味着朋友A和朋友B互相认识
每两组数据之间换行隔开
Output
对于每个测试用例,输出至少需要多少张桌子,不要打印多余的空格
Sample Input Copy
2
5 3
1 2
2 3
4 5
5 1
2 5
Sample Output Copy
2
4
#include<bits/stdc++.h>
using namespace std;
#define ios ios::sync_with_stdio(false); cin.tie(NULL);
const int N = 1010;
int t,n,m,a,b;
int pre[N];
int find_pre(int x)//路径压缩找父节点
{
if(x!=pre[x])
pre[x]=find_pre(pre[x]);
else
return pre[x];
return pre[x];
}
void join(int x,int y)
{
int a = find_pre(x);
int b = find_pre(y);
if(a!=b)
{
pre[a]=b;
}
}
int main()
{
cin>>t;
while(t--)
{
cin>>n>>m;
for(int i=1; i<=n; i++)//初始化
{
pre[i]=i;
}
while(m--)
{
cin>>a>>b;
join(a,b);
}
int vis[N]= {0}; //标记出现过的父节点
int cnt;
int ans=0;
for(int i=1; i<=n; i++)
{
cnt = find_pre(i);
if(vis[cnt]==0)
{
ans++;
vis[cnt]=1;
}
}
cout<<ans<<endl;
}
return 0;
}