原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1507
题意:一个n*m的矩阵,有k个格子被约束,在未被约束的格子中找到最多的组数满足:
1.每组两个格子;
2.两个格子相邻;
3.两个格子都不能被约束;
4.任何组的两个格子不能重复;
解析:其实很简单,建个二分图,求解最大匹配数,再输出路径即可。
建图左边是:下标和(i+j)为偶数;奇数放在右边。
我的图是以【1,1】为起点的,然后【1,2】,【1,3】,,,,,【2,1】,【2,2】,,,,
#define _CRT_SECURE_NO_DEPRECATE
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#define INF 99999999;
using namespace std;
int n, m, k;
int a[105][105];
int cx[10005];
int cy[10005];
int vis[10005];
int dir[4][2] = { 0,1,-1,0,0,-1,1,0 };
vector<int> vec[10005];
int dfs(int u)
{
for (int i = 0; i < vec[u].size(); i++)
{
int v = vec[u][i];
if (!vis[v])
{
vis[v] = 1;
if (cy[v] == -1 || dfs(cy[v]))
{
cx[u] = v;
cy[v] = u;
return 1;
}
}
}
return 0;
}
int hungarian()
{
memset(cx, -1, sizeof(cx));
memset(cy, -1, sizeof(cy));
int ans = 0;
for (int u = 1; u <= n*m; u++)
{
if (cx[u] == -1)
{
memset(vis, 0, sizeof(vis));
ans += dfs(u);
}
}
return ans;
}
int main()
{
int x, y;
while (~scanf("%d%d", &n, &m) && (n || m))
{
scanf("%d", &k);
memset(a, 0, sizeof(a));
for (int i = 0; i < k; i++)
{
scanf("%d%d", &x, &y);
a[x][y] = 1;
}
for (int i = 1; i <= n*m; i++)
vec[i].clear();
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
if ((i + j) % 2 == 0 && a[i][j] != 1)
{
for (int p = 0; p < 4; p++)
{
int ii = i + dir[p][0];
int jj = j + dir[p][1];
if (ii >= 1 && ii <= n&&jj >= 1 && jj <= m&&a[ii][jj] != 1)
vec[(i - 1)*m + j].push_back((ii - 1)*m + jj);//注意在i等于1的时候(i - 1)*m + j得到的值并不是我们想要的
}
}
}
}
int maxMatch = hungarian();
printf("%d\n", maxMatch);
int x1, y1, x2, y2;
for (int u = 1; u <= n*m; u++)
{
if (cx[u] != -1)
{
x1 = (u - 1) / m + 1;
y1 = (u - 1) % m + 1;
int v = cx[u];
x2= (v - 1) / m + 1;
y2= (v - 1) % m + 1;
printf("(%d,%d)--", x2, y2);
printf("(%d,%d)\n", x1, y1);
//printf("%d %d\n", u, v);
}
}
printf("\n");
}
return 0;
}