/*
二分图最大匹配,同时加上奇偶分离。用匈牙利算法增广找最大匹配及相互匹配的点对
*/
题目大意:有n*m的一块儿土地遗产,现在想要卖掉,已知黑格子是池塘不能卖,白格子需要两块儿连一起才能卖,问最多能卖多少个这样的可卖土地。
/**
划分奇偶
二分匹配
增广至最大匹配
*/
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
const int MAXV = 110;
struct node {
int x, y;
node() {
x = 0;
y = 0;
}
} match[MAXV][MAXV];
bool G[MAXV][MAXV], vis[MAXV][MAXV];
int f[4][2] = {{0, 1}, {0, -1}, {1, 0}, { -1, 0}};
int n, m;
bool find_AP ( int u, int v )
{
int x, y;
for ( int i = 0; i < 4; i++ ) {
x = u + f[i][0];
y = v + f[i][1];
if ( x <= 0 || y <= 0 || x > n || y > m )//界限
continue;
if ( !G[x][y] && !vis[x][y] ) { //扩展的那个顶点为白格子且未曾经过
vis[x][y] = 1; //标记
//如果拓展出的顶点为未盖点或该点是匹配点同时该匹配点另一侧的匹配点可继续增广
if ( !match[x][y].x || find_AP ( match[x][y].x, match[x][y].y ) ) {
match[x][y].x = u; //形成匹配
match[x][y].y = v;
return true;
}
}
}
return false;
}
int main() {
int k, ans, a, b;
while ( scanf ( "%d%d", &n, &m ) != EOF && ( n + m ) ) {
ans = 0;
memset ( G, 0, sizeof ( G ) );
memset ( match, 0, sizeof ( match ) );
for ( int i = 0; i <= n; i++ ) {
for ( int j = 0; j <= m; j++ ) {
match[i][j].x = 0;
match[i][j].y = 0;
}
}
scanf ( "%d", &k );
for ( int i = 0; i < k; i++ ) {
scanf ( "%d%d", &a, &b );
G[a][b] = 1; //顶点G[a][b]为黑格子
}
for ( int i = 1; i <= n; i++ ) {
for ( int j = 1; j <= m; j++ ) {
memset ( vis, 0, sizeof ( vis ) );//清空标记
//如果顶点i,j为白格子且i+j为奇数则从该顶点找增广路
if ( !G[i][j] && ( ( i + j ) & 1 ) ) {
if ( find_AP ( i, j ) ) //如果找到增广路,即多一条匹配
ans++;
}
}
}
printf ( "%d\n", ans );
for ( int i = 1; i <= n; i++ ) {
for ( int j = 1; j <= m; j++ ) {
if ( ! ( ( i + j ) & 1 ) ) {
if ( match[i][j].x != 0 )
printf ( "(%d,%d)--(%d,%d)\n", match[i][j].x, match[i][j].y, i, j );
}
}
}
}
printf ( "\n" );
return 0;
}