//二分图的一些简单想法 //二分图的最小覆盖点:假定选了一个点就相当于覆盖了以它为端点的所有边 //二分图的最小覆盖点集(在 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; } }
//鉴定完毕,我是个垃圾