题目传送门

好久没写博客了……

照这个速度,退役前怕是做不完网络流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攻击装置

01-07 10:54