poj2446 Chessboard 【最大匹配】

题目大意:一个n*m的棋盘,某些格子不能用,问用1*2的骨牌能否完全覆盖这个棋盘,当然,骨牌不能有重叠

思路:显然黑白染色后,一个骨牌只能覆盖一个白色格子和一个黑色格子,然后我们间二染色建图,看能否有完美匹配即可TUT

#include <iostream>
#include <cstdio>
#include <string.h>
#define maxn 10000
using namespace std;
const int dx[10]={0,0,0,-1,1};
const int dy[10]={0,1,-1,0,0};
int head[maxn],next[maxn],point[maxn],now=0,map[maxn][maxn],id[maxn],match[maxn],h;
bool visit[maxn];
void add(int x,int y)
{
    next[++now]=head[x];
    head[x]=now;
    point[now]=y;
}
int dfs(int k)
{
    for(int i=head[k];i;i=next[i])if(!visit[point[i]])
    {
        int u=point[i];
        visit[u]=1;
        if(match[u]==-1 || dfs(match[u]))
        {
            match[u]=k;
            return 1;
        }
    }
    return 0;
}
int main()
{
    int n,m,k,x,y,i;
    scanf("%d%d%d",&n,&m,&k);
    for(i=1;i<=k;i++)
    {
        scanf("%d%d",&y,&x);
        map[x][y]=2;
    }
    int ans=k;
    for(i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(map[i][j]!=2)map[i][j]=1;
        }
    }
    int fi=1;
    for(i=1;i<=n;i++)
    {
        fi^=1;
        for(int j=fi+1;j<=m;j+=2)if(map[i][j]==1)
        {
            id[++h]=(i-1)*m+j;
        //    printf("%d %d ",i,j);
            for(int kk=1;kk<=4;kk++)
            {
                int xx=i+dx[kk],yy=j+dy[kk];
                if(map[xx][yy]==1)
                {
                    add((i-1)*m+j,(xx-1)*m+yy);
                }
            }
        }
    }
    memset(match,-1,sizeof(match));
    for(i=1;i<=h;i++)
    {
        memset(visit,0,sizeof(visit));
        if(dfs(id[i]))ans+=2;
    }
    if(ans==n*m)printf("YES ");else printf("NO ");
    return 0;
}

原文地址:https://www.cnblogs.com/philippica/p/4078197.html