题意:给定一个n*m的矩阵,其中只有0和1,现在要从矩阵中删除所有的1,删除可以按下面的规则进行,对于某个为1的位置,可以选择删除在同一行或同一列所有的1。求最小删除次数。
思路:行的点集在左,列的点集在右。对于点(I,j)如果是1,则连一条I到j的边,跑一边匈牙利算法。
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int maxn = 1505;
vector<int> g[maxn];
int check[maxn],match[maxn];
int n,m;
bool dfs(int u)
{
for(int i=0;i<g[u].size();i++)//寻找增广路
{
int v=g[u][i];
if(!check[v])
{
check[v]=1;
if(match[v]==-1||dfs(match[v]))
{
match[v]=u;
match[u]=v;
return true;
}
}
}
return false;
}
int Hungarian()
{
int ans=0;
memset(match,-1,sizeof(match));
for(int i=1;i<=n;i++)
{
if(match[i]==-1)
{
memset(check,0,sizeof(check));
if(dfs(i))
++ans;
}
}
return ans;
}
int main()
{
int v;
//freopen("in.txt","r",stdin);
while(scanf("%d",&n)&&n)
{
scanf("%d",&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&v);
if(v)g[i].push_back(j+n);
}
int ans=Hungarian();
printf("%d\n",ans);
for(int i=1;i<=n+m;i++)g[i].clear();
}
}