CH6901 骑士放置
原题链接
和棋盘覆盖(题解)差不多.。
同样对格子染色,显然日字的对角格子是不同色,直接在对应节点连边,然后就是二分图最大独立集问题。
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 1e4 + 10;
const int M = 2.6e7 + 10;
int fi[N], di[M], ne[M], mtc[N], mo_x[8] = { -1, -2, -2, -1, 1, 2, 2, 1 }, mo_y[8] = { -2, -1, 1, 2, -2, -1, 1, 2 }, l, n, m;
bool v[N], a[102][102];
inline int re()
{
int x = 0;
char c = getchar();
bool p = 0;
for (; c < '0' || c > '9'; c = getchar())
p |= c == '-';
for (; c >= '0' && c <= '9'; c = getchar())
x = x * 10 + c - '0';
return p ? -x : x;
}
inline void add(int x, int y)
{
di[++l] = y;
ne[l] = fi[x];
fi[x] = l;
}
inline int ch(int x, int y)
{
return (x - 1) * m + y;
}
bool dfs(int x)
{
int i, y;
for (i = fi[x]; i; i = ne[i])
if (!v[y = di[i]])
{
v[y] = 1;
if (!mtc[y] || dfs(mtc[y]))
{
mtc[y] = x;
return true;
}
}
return false;
}
int main()
{
int i, x, y, j, s = 0, k, o;
n = re();
m = re();
k = re();
for (i = 1; i <= k; i++)
{
x = re();
y = re();
a[x][y] = 1;
}
for (i = 1; i <= n; i++)
for (j = 1; j <= m; j++)
if (!a[i][j] && !((i + j) & 1))
for (o = 0; o < 8; o++)
{
x = i + mo_x[o];
y = j + mo_y[o];
if (x > 0 && x <= n && y > 0 && y <= m && !a[x][y])
add(ch(i, j), ch(x, y));
}
for (i = 1; i <= n; i++)
for (j = 1; j <= m; j++)
if (!a[i][j] && !((i + j) & 1))
{
memset(v, 0, sizeof(v));
if (dfs(ch(i, j)))
s++;
}
printf("%d", n * m - s - k);
return 0;
}
posted on 2018-09-15 07:35 Iowa_Battleship 阅读(204) 评论(0) 编辑 收藏 举报