[JoyOI] 1035 棋盘覆盖 (二分图匹配)

题目描述
给出一张nn(n<=100)的国际象棋棋盘,其中被删除了一些点,问可以使用多少12的多米诺骨牌进行掩盖。

输入格式
第一行为n,m(表示有m个删除的格子)
第二行到m+1行为x,y,分别表示删除格子所在的位置
x为第x行
y为第y列

输出格式
一个数,即最大覆盖格数

提示
经典问题

样例数据
输入样例 #1
8 0
输出样例 #1
32

code:

//By Menteur_Hxy
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<ctime>
#include<queue>
#include<vector>
using namespace std;

const int MAX=500010;
const int INF=0x3f3f3f3f;

int n,m;
long long ans;
int match[10010];
bool jin[10010],vis[10010];
int book[4]={1,-1};

bool dfs(int u) {
    int y=(u-1)%n+1,x=(u-1)/n+1;
    for(int i=0;i<4;i++) {
        if((i==0&&y+1>n)||(i==1&&y-1<1)||(i==2&&x+1>n)||(i==3&&x-1<1)) continue;
        int v=u+book[i];
        if(jin[v]) continue;
        if(!vis[v]){
            vis[v]=1;
            if( !match[v] || dfs(match[v])) {
                match[v]=u; return true;
            }
        }
    }
    return false;
}

int main() {
    scanf("%d %d",&n,&m);
    book[2]=n,book[3]=-n;
    for(int i=1;i<=m;i++) {
        int x,y;
        scanf("%d %d",&x,&y);
        jin[(x-1)*n+y]=1;

    }
    for(int i=1;i<=n*n;i++) {
        int y=(i-1)%n+1,x=(i-1)/n+1;
        for(int j=1;j<=n*n;j++) vis[j]=0;
        if((y+x&1)&1 && !jin[i]) 
            if(dfs(i)) ans++;
    }
    printf("%lld",ans);
    return 0;
}
posted @ 2018-03-07 01:50  Menteur_hxy  阅读(241)  评论(0编辑  收藏  举报