题目不仅要求输出最大匹配,还要输出任意一种最大匹配组,大意是给出n*m的矩阵,给出num个放个不能放东西,一个东西要占两格,因此把根据每个可用的格子的行i和列j和的单双来建立图。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
#include <cstdlib>
#include <iomanip>
using namespace std;
const int maxn=111;
const int maxm=1111;
int map[maxm][maxm];
int g[maxm][maxm];
int n,m;
int fn,fm;
int link[maxm];
int visit[maxm];
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
bool in(int x,int y)
{
if(x>=1&&x<=n&&y>=1&&y<=m)
{
return true;
}
return false;
}
bool dfs(int k)//寻找从k出发的可增广路
{
int i,j;
for(int i=1;i<=fm;i++)
{
if(g[k][i]&&!visit[i])
{
visit[i]=1;//加入增广路
j=link[i];
if(j==-1||dfs(j))//j是未盖点 或者 从j的对应项出发有可增广路)
{
link[i]=k;
return true;//k有可增广路,返回true;
}
}
}
return false;//则从k没有可增广路,返回false;
}
int hungary()
{
int num=0;
memset(link,-1,sizeof(link));//初始化
for(int i=1;i<=fn;i++)
{
memset(visit,0,sizeof(visit));
if(dfs(i))//有增广路
{
num++;//匹配数++
}
}
return num;
}
int main()
{
int num;
int p,q;
int a[maxm];
int cnt;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==0&&m==0)
{
break;
}
cnt=1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
map[i][j]=1;
}
}
memset(g,0,sizeof(g));
scanf("%d",&num);
while(num--)
{
scanf("%d%d",&p,&q);
map[p][q]=0;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(map[i][j]==1)
{
a[cnt]=i*m+j;
map[i][j]=cnt++;
}
}
}
fn=fm=cnt;
//cout<<cnt<<endl;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if((map[i][j]!=0)&&((i+j)%2==1))
{
for(int t=0;t<4;t++)
{
int x=i+dir[t][0];
int y=j+dir[t][1];
//cout<<i<<" "<<j<<" "<<x<<" "<<y<<endl;
if(in(x,y)&&map[x][y]!=0)
{
g[map[i][j]][map[x][y]]=1;
}
}
}
}
}
int ans=hungary();
printf("%d\n",ans);
for(int i=1;i<=fn;i++)
if(link[i]!=-1)
{
//cout<<link[i]<<endl;
//cout<<a[i]<<" "<<a[link[i]]<<endl;
int x1=(a[i]-m-1)/m;
int y1=(a[i]-1-m)%m;
int x2=(a[link[i]]-m-1)/m;
int y2=(a[link[i]]-1-m)%m;
printf("(%d,%d)--(%d,%d)\n",x1+1,y1+1,x2+1,y2+1);
}
printf("\n");
}
return 0;
}