//二分图的一些简单想法
//二分图的最小覆盖点:假定选了一个点就相当于覆盖了以它为端点的所有边
//二分图的最小覆盖点集(在 X集合和Y集合中选取最少的点可以将图中所有的边都覆盖)
//最小覆盖点集数 == 二分图的最大匹配数
//结论证明:https://www.cnblogs.com/jianglangcaijin/p/6035945.html (ORZ)
//例题 HDU 2119(板子)
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 100 + 15;
bool Grape[maxn][maxn];//思路:以横轴和纵轴建立二分图,if Grape[i][j] == true,则证明i j之间存在边,转换为最小覆盖点集问题
int n,m;
bool vis[maxn];
int match[maxn];
bool Hungary(int u)//寻找增广路
{
for(int v=1;v<=m;++v)
{
if(!vis[v]&&Grape[u][v])
{
vis[v] = true;
if(match[v]==-1||Hungary(match[v]))
{
match[v] = u;
return true;
}
}
}
return false;
}
int solve()
{
memset(match,-1,sizeof(match));
int cnt = 0;
for(int u=1;u<=n;++u)
{
memset(vis,false,sizeof(vis));
if(Hungary(u))
++cnt;
}
return cnt;
}
int main()
{
while(cin>>n&&n)
{
cin>>m;
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
cin>>Grape[i][j];
cout<<solve()<<endl;
}
}
知识兔//鉴定完毕,我是个垃圾