Matrix
Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3543 Accepted Submission(s): 1657
Problem Description
Give you a matrix(only contains 0 or 1),every time you can select a row or a column and delete all the '1' in this row or this column .
Your task is to give out the minimum times of deleting all the '1' in the matrix.
Input
There are several test cases.
The first line contains two integers n,m(1<=n,m<=100), n is the number of rows of the given matrix and m is the number of columns of the given matrix.
The next n lines describe the matrix:each line contains m integer, which may be either ‘1’ or ‘0’.
n=0 indicate the end of input.
Output
For each of the test cases, in the order given in the input, print one line containing the minimum times of deleting all the '1' in the matrix.
Sample Input
3 3 0 0 0 1 0 1 0 1 0 0
Sample Output
2
Author
Wendell
Source
HDU 2007-10 Programming Contest_WarmUp
Recommend
威士忌
题意:
给你一个N*M的0/1矩阵,你每次可以选特定的某行或某列,然后删除该行/列的所有1,问你最少需要几次操作能删除矩阵的所有1.
分析:
我们将矩阵中点值为1的点的横纵坐标间建立建二分图,因为我们要消除全部的1,所以我们不是要选择这一点的行或者这一点的列,这样就转化为最小覆盖要求用最少的点,最少的点(即覆盖数)=最大匹配数 M。
简单的证明如下:
(1)M个是足够的。只需要让它们覆盖最大匹配的M条边,则其它边一定被覆盖(如果有边e不被覆盖,把e加入后得到一个更大的匹配)
(2)M个是必需的,仅考虑形成最大匹配的这M条边,由于它们两两之间没有公共点,因此至少需要M个点才可以把它们覆盖
//二分图最大匹配模板,二分图都是无向图
//调用下面算法前,保证本图是二分图
/*************vecotr模板*****************/
#include<cstdio>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<functional>
#include<cstring>
#include<string>
#include<cstdlib>
#include<iomanip>
#include<numeric>
#include<cctype>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<list>
#include<set>
#include<map>
using namespace std;
const int maxn = 510;
struct Max_Match
{
int n,m;//左右点集大小,点从1开始编号
vector<int> g[maxn];//g[i]表示左边第i个点邻接的右边点的集合
bool vis[maxn];//vis[i]表示右边第i个点是否在本次match中被访问过
int left[maxn];//left[i]==j表右边第i个点与左边第j个点匹配,为-1表无点匹配
void init(int n,int m)
{
this->n = n;
this->m = m;
for (int i = 0; i <= n; i++) g[i].clear();
memset(left, -1, sizeof(left));
}
//判断从左u点是否可以找到一条增广路
bool match(int u)
{
for (int i = 0; i<g[u].size(); i++)
{
int v = g[u][i];
if (!vis[v])
{
vis[v] = true;
if (left[v] == -1 || match(left[v]))//找到增广路
{
left[v] = u;
return true;
}
}
}
return false;
}
//返回当前二分图的最大匹配数
int solve()
{
int ans = 0;//最大匹配数
for (int i = 1; i <= n; i++)//每个左边的节点找一次增广路
{
memset(vis, 0, sizeof(vis));
if (match(i)) ans++;//找到一条增广路,形成一个新匹配
}
return ans;
}
}MM;
/*************vecotr模板*****************/
int main()
{
int n, m;
while (scanf("%d", &n)!=-1 && n)
{
scanf("%d", &m);
MM.init(n, m);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
{
int v;
scanf("%d", &v);
if (v) MM.g[i].push_back(j);
}
printf("%d\n", MM.solve());
}
return 0;
}