题目大意
给一个01矩阵,求最对能分割出几块由0构成的1 * 2的矩阵
思路
抽象出二分图,相邻的0之间建边,匈牙利算法求最大匹配数
给一个01矩阵,求最对能分割出几块由0构成的1 * 2的矩阵
思路
抽象出二分图,相邻的0之间建边,匈牙利算法求最大匹配数
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#define INF 0x3f3f3f3f
#define rep0(i, n) for (int i = 0; i < n; i++)
#define rep1(i, n) for (int i = 1; i <= n; i++)
#define rep_0(i, n) for (int i = n - 1; i >= 0; i--)
#define rep_1(i, n) for (int i = n; i > 0; i--)
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define mem(x, y) memset(x, y, sizeof(x))
#define MAXN 110
using namespace std;
struct Edge
{
int from, to;
Edge(int f, int t) : from(f), to(t) {}
};
vector<Edge> edges;
vector<int> g[MAXN * MAXN];
int land[MAXN][MAXN], matching[MAXN * MAXN], check[MAXN * MAXN];
void addEdge(int from, int to)
{
edges.push_back(Edge(from, to));
g[from].push_back(edges.size() - 1);
edges.push_back(Edge(to, from));
g[to].push_back(edges.size() - 1);
}
int n, m, k;
bool dfs(int u)
{
for (int i = 0; i < g[u].size(); i++)
{
int v = edges[g[u][i]].to;
if (check[v])
continue;
check[v] = 1;
if (matching[v] == -1 || dfs(matching[v]))
{
matching[v] = u;
matching[u] = v;
return true;
}
}
return false;
}
int hungarian()
{
int ans = 0;
for (int i = 1; i <= n; i++)
{
for (int j = (i - 1) % 2 + 1; j <= m; j += 2)
{
if (land[i][j] == 1)
continue;
mem(check, 0);
if (dfs((i - 1) * m + j))
ans++;
}
}
return ans;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif // ONLINE_JUDGE
while (~scanf("%d %d %d", &n, &m, &k) && n)
{
mem(land, 0);
mem(matching, -1);
int a, b;
edges.clear();
rep1(i, n * m)
g[i].clear();
while (k--)
{
scanf("%d %d", &a, &b);
land[a][b] = 1;
}
rep1(i, n)
{
rep1(j, m)
{
if (land[i][j] == 1)
continue;
if (i > 1 && land[i - 1][j] == 0)
addEdge((i - 1) * m + j, (i - 2) * m + j);
if (j > 1 && land[i][j - 1] == 0)
addEdge((i - 1) * m + j, (i - 1) * m + j - 1);
}
}
printf("%d\n", hungarian());
}
return 0;
}