//简单的匈牙利算法模板题。。题意是奶牛在自己喜欢的牛栏里才有最大的产量,有N头牛,M个牛栏。求最大产量。
//如果mk[i]=0表示未访问过,如果为1表示访问过
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
const int maxn=500;
int mk[maxn];
int nx,ny; //X和Y集合中顶点的个数
int g[maxn][maxn]; //邻接矩阵, X集合和Y集合中顶点间边的信息
int cx[maxn],cy[maxn];
int path(int u)
{
for(int v=1;v<=ny; v++) //考虑所有Yi顶点v
{
if(g[u][v]&&!mk[v])
{
mk[v]=1;
if(cy[v]==-1||path(cy[v]))
{
cx[u] = v; //把v匹配给u
cy[v] = u; //把u匹配给v
return 1; //找到可增广路
}
}
}
return 0 ; //如果不存在从u出发的增广路
}
int MaxMatch() //求二部图最大匹配的匈牙利算法
{
int res=0;
int i;
memset(cx,0xff,sizeof(cx)) ;
memset(cy,0xff,sizeof(cy)) ;
for(i=1;i<=nx;i++)
{
if(cx[i]==-1) //从每个未盖点出发进行寻找增广路
{
memset(mk,0,sizeof(mk));
res+=path(i); //每找到一条增广路,可使得匹配数加1
}
}
return res;
}
int main()
{
int n,m;
int i,j;
int num,ans;
while(scanf("%d%d",&n,&m)!=EOF)
{
nx=n;ny=m;
memset(g,0,sizeof(g));
for(i=1;i<=n;i++)
{
scanf("%d",&num);
for(j=1;j<=num;j++)
{
scanf("%d",&ans);
g[i][ans]=1;
}
}
printf("%d\n",MaxMatch());
}
return 0;
}