1507 Uncle Tom's Inherited Land* 二分图-----黑白染色+奇偶匹配(1X2的矩形覆盖)

要把 图分成两部分,即 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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值