好久没写博客了……
照这个速度,退役前怕是做不完网络流24题了
和方格取数其实差不多,还是黑白染色,建出图来之后跑匈牙利求最大匹配数就好了
最后答案是 格子数量 减去 障碍数量和最大匹配数
#include <iostream>
#include <cstdio>
#include <cstring>
#define LL long long
using namespace std;
LL read() {
LL k = 0, f = 1; char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9')
k = k * 10 + c - 48, c = getchar();
return k * f;
}
struct zzz {
int t, nex;
}e[100010 << 1]; int head[40010], tot;
inline void add(int x, int y) {
e[++tot].t = y;
e[tot].nex = head[x];
head[x] = tot;
}
int n, m, num[210][210];
bool mapp[2010][2010];
int fx[9] = {0, -2, -1, 1, 2, 2, 1, -1, -2},
fy[9] = {0, 1, 2, 2, 1, -1, -2, -2, -1};
bool vis[40010]; int lin[40010];
bool find(int x) {
for(int i = head[x]; i; i = e[i].nex) {
int to = e[i].t;
if(!vis[to]) {
vis[to] = 1;
if(!lin[to] || find(lin[to])) {
lin[to] = x; return 1;
}
}
}
return 0;
}
int q[100010], top;
int main() {
n = read(), m = read();
for(int i = 1; i <= m; ++i) {
int x = read(), y = read();
mapp[x][y] = 1;
}
int cnt = 0;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j)
num[i][j] = ++cnt;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j) {
if(mapp[i][j] || !(i+j & 1)) continue;
q[++top] = num[i][j];
for(int k = 1; k <= 8; ++k) {
int x = i + fx[k], y = j + fy[k];
if(x <= 0 || x > n || y <= 0 || y > n || mapp[x][y]) continue;
add(num[i][j], num[x][y]);
}
}
int ans = 0;
for(int i = 1; i <= top; ++i) {
memset(vis, 0, sizeof(vis));
ans += find(q[i]);
}
cout << n * n - ans - m;
return 0;
}
其实上面的代码在Luogu上会T掉一个点,可能被卡常了吧 ……
双倍经验:TJOI2013攻击装置