hdu1507最大匹配

时间:2023-03-09 04:10:52
hdu1507最大匹配

题意:给出n*m的矩阵方块,某些方块是ponds,这些方块不能出售,然后能出售的是1*2的方块

要求求出有多少块1*2的方块能够出售,并输出这些方块的坐标(specia judge)

关键是怎么建出二分图,然后找最大匹配

可以把i+j==奇数的点提取出来,成为X集合,那么与(i,j)相邻的点就是Y集合了,然后就是二分图最大匹配

 //关键在于建图
#include <stdio.h>
#include <string.h>
#include <vector>
using namespace std;
const int N = +;
int Map[][];
int n,m,k;
vector<int> G[N];
int dx[] = {,,-,};
int dy[] = {-,,,};
bool vis[N];
int cy[N];
int cx[N];
bool dfs(int u)
{
for(int i=; i<G[u].size(); ++i)
{
int v = G[u][i];
if(!vis[v])
{
vis[v] = true;
if(cy[v] == - || dfs(cy[v]))
{
cy[v] = u;
cx[u] = v;
return true;
}
}
}
return false;
}
int MaxMatch()
{
memset(cy, -, sizeof(cy));
memset(cx, -, sizeof(cx));
int t = m * n;
int cnt = ;
for(int i=; i<t; ++i)
{
if(cx[i] == -)
{
memset(vis,,sizeof(vis));
cnt += dfs(i);
}
}
return cnt;
}
int main()
{
int i,j,x,y;
while(true)
{
scanf("%d%d",&n,&m);
if(n== && m==)
break;
scanf("%d",&k);
for(i=; i<N; ++i)
G[i].clear();
memset(Map, , sizeof(Map));
for(i=; i<k; ++i)
{
scanf("%d%d",&x,&y);
x-=; y-=;
Map[x][y] = ;
}
for(i=; i<n; ++i)
for(j=; j<m; ++j)
if(Map[i][j] == && (i+j)&==)
{
x = i * n + j;
for(k=; k<; ++k)
{
int a = dx[k] + i;
int b = dy[k] + j;
if(a>= && b>= && a<n && b<m && Map[a][b] == )
{
y = a * n + b;
G[x].push_back(y);
}
}
}
int ans = MaxMatch();
printf("%d\n",ans);
int t = n * m;
for(i=; i<t; ++i)
if(cx[i] != -)
printf("(%d,%d)--(%d,%d)\n",i/n+,i%n+,cx[i]/n+,cx[i]%n+); }
return ;
}