要把 图分成两部分,即 0 1 交替出现 每个0 上下左右 都是1,1的上下左右都是0 。 待覆盖的点(非池塘)中 为0的点 为一个点集,为1的为另一个点集。每个点与周围的4个点(非池塘)有线连接。 这时,二分图建完了。
之后就是求最大二分匹配,输出路径(只用maty[] 就可以了,我却想的很麻烦 ,弱智啊)
主要是如何建图!
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<vector>
using namespace std;
#define max(a,b) (a)>(b)? (a):(b)
#define min(a,b) (a)>(b)? (b):(a)
#define INT_MIN -0x7FFFFFFF
#define INF 100000000
#define N 105
#define M 105
int n,m,k;
int map1[N][M],map2[N][M];
int maty[N*M/2],ty[N*M/2];
int map[N][N];
struct node
{
int x,y;
node(int a,int b)
{
x=a;
y=b;
}
};
vector<struct node> po1,po2;
int test(struct node a,struct node b)
{
if(abs(a.x-b.x)==1 && a.y==b.y) return 1;
if(abs(a.y-b.y)==1 && a.x==b.x) return 1;
else return 0;
}
int path(int x)
{
int i,j,k;
for(i=0;i<po2.size();i++)
{
if(map[x][i] && !ty[i])
{
ty[i]=1;
if( maty[i]<0 || path(maty[i]) )
{
maty[i]=x;return 1;
}
}
}
return 0;
}
int main()
{
//freopen("in.txt","r",stdin);
int i,j;
for(i=1;i<=100;i++)
{
for(j=1;j<=100;j++)
{
if((i&1 && j&1)||(!(i&1) && !(j&1))) map1[i][j]=1;
else map1[i][j]=0;
}
}
while(scanf("%d%d",&n,&m),n||m)
{
scanf("%d",&k);
int a,b;
po1.clear();
po2.clear();
memset(map2,0,sizeof(map2));
for(i=1;i<=k;i++)
{
scanf("%d%d",&a,&b);
map2[a][b]=1;
}
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
if(!map2[i][j])
{
if(map1[i][j]) po1.push_back(node(i,j));
else po2.push_back(node(i,j));
}
}
}
memset(map,0,sizeof(map));
for(i=0;i<po1.size();i++)
{
for(j=0;j<po2.size();j++)
{
if(test(po1[i],po2[j]))
map[i][j]=1;
}
}
memset(maty,-1,sizeof(maty));
int ans=0;
for(i=0;i<po1.size();i++)
{
memset(ty,0,sizeof(ty));
ans+=path(i);
}
printf("%d\n",ans);
for(i=0;i<po2.size();i++)
{
int tt=maty[i];
if(tt!=-1)
printf("(%d,%d)--(%d,%d)\n",po2[i].x,po2[i].y,po1[tt].x,po1[tt].y);
}
puts("");
}
return 0;
}