/************************************************************************/
/* *Author:justinzhang
/*Email:uestczhangchao@gmail.com
/*Establish:2011年5月14日16:43:46
/*Discription:算法导论22章并查集&&poj1611 */
/************************************************************************/
#include<iostream>
using namespace std;
/*
*rank[]是用来存放元素x秩的数组,p[]是用来存放元素x父节点的数组
*Make_Set()用来初始化集合元素,刚开始的时候每个元素独立为一个集合
*/
void Make_Set(int rank[],int p[],int x)
{
p[x] = x;
rank[x] = 0;
}
/************************************************************************/
/* 寻找x元素所属的集合 */
/************************************************************************/
int Find_Set(int p[],int x)
{
if(p[x]!=x)
{
p[x] = Find_Set(p,p[x]);
}
return p[x];
}
/************************************************************************/
/* 合并两个集合 */
/************************************************************************/
void Union(int rank[],int p[],int x, int y)
{
int px = Find_Set(p,x);
int py = Find_Set(p,y);
if (rank[px]>rank[py])
{
p[py] = px;
}
else
{
p[px] = py;
if (rank[px]==rank[py])
{
rank[py]++;
}
}
}
int main()
{
int n, m;
int rank[30003];
int p[30003];
int numsuspect;
int personnum;
int firstpersonnum;
int groupnum;
int i,j;
while(1)
{
numsuspect = 0;
memset(rank,0,sizeof(rank));
memset(p,0,sizeof(p));
cin >> n >> m;//n为学生人数,m为学生的分组数
if(n==0 && m==0)
break;
for(j=0;j<n;j++)
Make_Set(rank,p,j);
while((--m)>=0)
{
cin>>groupnum;
if (groupnum>=1)
{
cin>>firstpersonnum;
}
for(i=1;i<groupnum;i++)
{
cin >> personnum;
Union(rank,p,firstpersonnum,personnum);
}
}
for (j=0;j<n;j++)
{
if (Find_Set(p,0)==Find_Set(p,j))
{
numsuspect++;
}
}
cout << numsuspect << endl;
}
system("pause");
return 0;
}