POJ 2446 Chessboard【二分图匹配】

题意: 给你一个 n*m 的方格,但是里面有些地方是有洞的,问你能否用1 X 2 的板砖铺满空白的地方,

   例如:    

分析: 二分图匹配,关键在于建图,以奇数格(i+j)%2==1 为一个集合,以偶数格为另一个集合,因为任意一个铺设都是有一个奇数格和一个偶数格构成的,

    最后如果匹配的个数是空白格数的一半,即完全匹配,说明能够铺满。

View Code
#include<stdio.h>
#include<string.h>
#define clr(x)memset(x,0,sizeof(x))
struct node
{
    int to,next;
}q[1000000];
int head[1200];
int link[1200];
int v[1200];
int tot;
void add(int s,int u)
{
    q[tot].to=u;
    q[tot].next=head[s];
    head[s]=tot++;
}
int find(int x)
{
    int i,k;
    for(i=head[x];i;i=q[i].next)
    {
        k=q[i].to;
        if(!v[k])
        {
            v[k]=1;
            if(link[k]==0||find(link[k]))
            {
                link[k]=x;
                return 1;
            }
        }
    }
    return 0;
}
int map[35][35];
int s[1205];
int main()
{
    int sn,i,n,j,m,k,a,b,sum,flag;
    while(scanf("%d%d%d",&n,&m,&k)!=EOF)
    {
        if((n*m-k)&1)
        {
            printf("NO\n");
            continue;
        }
        clr(head);
        clr(link);
        tot=1;
        for(i=1;i<=k;i++)
        {
            scanf("%d%d",&a,&b);
            map[b][a]=1;
        }
        sn=0;
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            {
                flag=0;
                if(((i+j)&1)&&map[i][j]==0)
                {
                    if(i>1&&map[i-1][j]==0)
                    {
                        add(i*m+j,(i-1)*m+j);
                        flag=1;
                    }
                    if(j>1&&map[i][j-1]==0)
                    {
                        add(i*m+j,i*m+j-1);
                        flag=1;
                    }
                    if(i<n&&map[i+1][j]==0)
                    {
                        add(i*m+j,(i+1)*m+j);
                        flag=1;
                    }
                    if(j<m&&map[i][j+1]==0)
                    {
                        add(i*m+j,i*m+j+1);
                        flag=1;
                    }
                    if(flag)
                        s[sn++]=i*m+j;
                }
            }
        }
        sum=0;
        for(i=0;i<sn;i++)
        {
            clr(v);
            if(find(s[i]))
                sum++;
        }
        if(sum==(n*m-k)/2)
            printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

 

posted @ 2012-04-23 17:13  'wind  阅读(165)  评论(0)    收藏  举报