

//思路:把所有认识的朋友组成一棵树,只要知道有几棵树,就知道需要几张桌子了。(这里的树为了方便查找根,将子节点指向根节点) 初始化时将所有树的根设为-1;
//通过依次读入认识的朋友(a,b),利用find查找当前朋友(a)的上级节点,然后利用connect将上级节点和b连通。即(friends[find(a)]=b)。(如果没有上及节点(即friends[a]=-1),则直接friends[a]=b)
//最后遍历所有人,将根放入set容器中,输出容器的大小即为桌子数量。
#include<iostream>
#include<set>
using namespace std;
int friends[1001];
int find(int i)//递归查找当前节点的上级节点如果friends[i]<0,当前节点即为最上级
{
if(friends[i]>0)
{
i=friends[i];
find(i);
}
else
{
return i;
}
}
void connect(int n,int m)
{
int x=find(n);
int y=find(m);
if(x!=y) //如果已经链接过,就不在链接
{
friends[x]=y;
}
}
int searchroot(int n)
{
set<int> tables; //利用set容器内部能存放相同元素的特性,可以很容易知道当前哪些节点的根式相同的。
for(int i=1;i<=n;i++)
tables.insert(find(i));
return tables.size();
}
int main()
{
int T,n,m,a,b,count,i;
cin>>T;
while(T--)
{
cin>>n>>m;
fill(friends,friends+n+1,-1);//前两个参数为地址。在此地址内填充-1.头文件iostream. 注意:要想填充到第n个数,必须为n+1。(最初在此出错,但我测试过如果不将此全局数组填充为-1,在vc6.0下默认是全部初始化为0的,按照这样应该不影响结果。估计HDOJ不是默认初始化。悲剧哈!)
for(i=0;i<m;i++)
{
cin>>a>>b;
connect(a,b);
}
cout<<searchroot(n)<<"\n";
}
return 0;
}