AcWing 372. 棋盘覆盖
原题链接
中等
作者:
Anoxia_3
,
2020-08-14 15:29:48
,
所有人可见
,
阅读 574
/*
将每个格子看成是点,每一个骨牌看做是一条边,
那么要求就变成找出最多的边,且没有这些边中没有公共点,
这就是求最大匹配,为了将这幅图变成二分图,可以先将棋盘染色,横纵坐标是偶数的染白色,奇数染黑色。
匹配:一条边没有相同点
最大匹配:匹配的最大数量
增广路径:从一个未匹配点出发,经过未匹配边、匹配边、未匹配边、匹配边、...、未匹配边,最后到了未匹配点的路径。如果存在增广路径,则未达到最大匹配
最大匹配<=>不存在增广路径
*/
#include <iostream>
#include <cstring>
#define x first
#define y second
using namespace std;
typedef pair<int , int> PII;
const int N = 110;
PII match[N][N];
bool st[N][N];
int n , m;
bool g[N][N];
int dx[4] = {-1 , 0 , 1 , 0} , dy[4] = {0 , 1 , 0 , -1};
bool find(int x , int y)
{
for(int i = 0 ; i < 4 ; i++)
{
int a = x + dx[i] , b = y + dy[i];
if(a && a <= n && b && b <= n && !g[a][b] && !st[a][b])
{
st[a][b] = true;
PII t = match[a][b];
if(t.x == 0 || find(t.x , t.y))
{
match[a][b] = {x , y};
return true;
}
}
}
return false;
}
int main()
{
cin >> n >> m;
while(m--)
{
int x , y;
cin >> x >> y;
g[x][y] = true;
}
int res = 0;
for(int i = 1 ; i <= n ; i++)
for(int j = 1 ; j <= n ; j++)
if((i + j) % 2 == 1 && !g[i][j])
{
memset(st , 0 , sizeof st);
if(find(i , j)) res++;
}
cout << res << endl;
return 0;
}