/*
codevs2776 寻找代表元
二分图 最大流 Dinic
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 2010
#define INF 9999185
using namespace std;
int head[maxn],deep[maxn],q[maxn],vis[maxn];
int n,m,x,y,z,cnt,cut=1,ans,S,T;//注意cut=1!!! 因为后面要^
struct node
{
int u,v,next,flow;
}e[maxn<<5];
inline int init()
{
int x=0,f=1;char c=getchar();
while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
inline void add(int u,int v,int c)
{
e[++cut].v=v;e[cut].flow=c;e[cut].next=head[u];head[u]=cut;
e[++cut].v=u;e[cut].flow=0;e[cut].next=head[v];head[v]=cut;
}
int BFS()//统计各点的层数
{
memset(deep,-1,sizeof deep);
int first=0,last=0;
q[last++]=S;deep[S]=0;
while(first<last)
{
int now=q[first++];
for(int i=head[now];i;i=e[i].next)
{
int v=e[i].v;
if(deep[v]==-1&&e[i].flow>0)
{
deep[v]=deep[now]+1;
if(v==T) return true;//找到终点就return true
q[last++]=v;
}
}
}
return false;
}
int dfs(int now,int came_flow)//now 是当前节点,came_flow是能流过来的流量,即当前点准备向外流的流量。
{
int use_flow=0;//这个点已经往外流的量
if(now==T) return came_flow;//流到终点
for(int i=head[now];i;i=e[i].next)//&&use_flow<came_flow 据说这是各优化,不懂23333
{
int v=e[i].v;
if(e[i].flow>0&&deep[v]==deep[now]+1)//往下一层
{
int min_flow=min(e[i].flow,came_flow-use_flow);//这个边是能流这个边流量还是剩下的流量
min_flow=dfs(v,min_flow);//当前增广路找到终点时的流量
use_flow+=min_flow;//用的加上
e[i].flow-=min_flow;//当前流量减去用的
e[i^1].flow+=min_flow;//反向弧加上用的
}
}
if(!use_flow)//优化 如果找到到不了汇点的点,就不管它。
deep[now]=-1;
return use_flow;
}
int Dinic()
{
while(BFS())//如果有增广路
{
ans+=dfs(S,INF);
}
return ans;
}
int main()
{
int x,y;
n=init(),m=init();S=0,T=n+m+1;
for(int i=1;i<=n;i++) add(S,i,1);
for(int i=1;i<=m;i++) add(n+i,T,1);
for(int i=1;i<=n;i++)
{
while(true)
{
x=init();
if(!x) break;
add(i,n+x,1);
}
}
printf("%d",Dinic());
return 0;
}