[lnsyoj2604/luoguP3355] 骑士共存问题

题意

给定 n×n 的棋盘,有 m 个障碍,问可以放置多少个不同的互不攻击的马。

sol

类似于 [lnsyoj2605/luoguP2774] 方格取数问题,对于本题,每个点有最多 8 个相斥的点,且横纵坐标的和的奇偶性一定不同,因此参照上题即可做出

代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>

using namespace std;

const int N = 40005, M = 500005, INF = 0x3f3f3f3f, K = 205;;

int h[N], e[M], cap[M], ne[M], idx;
int d[N], cur[N];
int n, S, T;
int s, m;
bool g[K][K];
int dx[8] = {2, 2, 1, -1, -2, -2, -1, 1}, dy[8] = {-1, 1, 2, 2, 1, -1, -2, -2};

void add(int a, int b, int c){
    e[idx] = b, cap[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
    e[idx] = a, cap[idx] = 0, ne[idx] = h[b], h[b] = idx ++ ;
}

void build(){
    memset(h, -1, sizeof h);
    n = s * s + 2;
    S = n - 1, T = n;
    for (int i = 1; i <= s; i ++ )
        for (int j = 1; j <= s; j ++ )
            if (!g[i][j]) {
                int id = (i - 1) * s + j;
                if ((i + j) % 2) {
                    add(S, id, 1);
                    for (int u = 0; u < 8; u ++ ) {
                        int sx = i + dx[u], sy = j + dy[u];
                        if (sx < 1 || sx > s || sy < 1 || sy > s || g[sx][sy]) continue;
                        int sid = (sx - 1) * s + sy;
                        add(id, sid, INF);
                    }
                }
                else add(id, T, 1);
            }
}

bool bfs(){
    memset(d, -1, sizeof d);
    queue<int> q;
    q.push(S), cur[S] = h[S], d[S] = 0;
    while (!q.empty()) {
        int t = q.front(); q.pop();
        for (int i = h[t]; ~i; i = ne[i]){
            int j = e[i];
            if (d[j] == -1 && cap[i]) {
                d[j] = d[t] + 1;
                cur[j] = h[j];
                if (j == T) return true;
                q.push(j);
            }
        }
    }
    return false;
}

int find(int u, int limit){
    if (u == T) return limit;
    int flow = 0;
    for (int i = cur[u]; ~i && flow < limit; i = ne[i]){
        int j = e[i];
        cur[u] = i;
        if (d[j] == d[u] + 1 && cap[i]) {
            int t = find(j, min(cap[i], limit - flow));
            if (!t) d[j] = -1;
            cap[i] -= t, cap[i ^ 1] += t, flow += t;
        }
    }
    return flow;
}

int dinic(){
    int r = 0, flow;
    while (bfs()) while (flow = find(S, INF)) r += flow;
    return r;
}

int main(){
    scanf("%d%d", &s, &m);
    int cnt = s * s;
    while (m -- ){
        int x, y;
        scanf("%d%d", &x, &y);
        if (g[x][y]) continue;
        g[x][y] = true;
        cnt -- ;
    }

    build();

    int t = dinic();

    printf("%d\n", cnt - t);
}
posted @   是一只小蒟蒻呀  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示