[TJOI2013] 攻击装置

给定 (N imes N) 棋盘,某些格子是障碍,问可以放置的互不侵犯的马的个数

黑白染色后建立二分图,求最大独立集 = 总点数 - 最大匹配数

注意把反边也连上会WA掉(脑抽一发血)

#include <bits/stdc++.h>
using namespace std;

// Input: make(u,v,w)
// Solver: int solve(s,t);
// Output: ans(returned)
namespace flow {

const int maxn = 300005;
const int inf = 1e+9;

int dis[maxn], ans, cnt = 1, s, t, pre[maxn * 10], nxt[maxn * 10], h[maxn], v[maxn * 10];
std::queue<int> q;
void make(int x, int y, int z) {
    pre[++cnt] = y, nxt[cnt] = h[x], h[x] = cnt, v[cnt] = z;
    pre[++cnt] = x, nxt[cnt] = h[y], h[y] = cnt;
}
bool bfs() {
    memset(dis, 0, sizeof dis);
    q.push(s), dis[s] = 1;
    while (!q.empty()) {
        int x = q.front();
        q.pop();
        for (int i = h[x]; i; i = nxt[i])
            if (!dis[pre[i]] && v[i])
                dis[pre[i]] = dis[x] + 1, q.push(pre[i]);
    }
    return dis[t];
}
int dfs(int x, int flow) {
    if (x == t || !flow)
        return flow;
    int f = flow;
    for (int i = h[x]; i; i = nxt[i])
        if (v[i] && dis[pre[i]] > dis[x]) {
            int y = dfs(pre[i], min(v[i], f));
            f -= y, v[i] -= y, v[i ^ 1] += y;
            if (!f)
                return flow;
        }
    if (f == flow)
        dis[x] = -1;
    return flow - f;
}
int solve(int _s,int _t) {
    s=_s;
    t=_t;
    ans = 0;
    for (; bfs(); ans += dfs(s, inf));
    return ans;
}
}

int n,cnt;
char s[205][205];

const int dx[9]={0,1,1,-1,-1,2,2,-2,-2};
const int dy[9]={0,2,-2,2,-2,1,-1,1,-1};

int check(int i,int j) {
    if(i>0 && j>0 && i<=n && j<=n && s[i][j]=='0') return 1;
    return 0;
}

int main() {
    cin>>n;
    for(int i=1;i<=n;i++) cin>>s[i]+1;
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=n;j++) {
            if(check(i,j)) {
                ++cnt;
                if((i+j)&1) flow::make(n*n+1,i*n-n+j,1);
                else flow::make(i*n-n+j,n*n+2,1);
            }
            if((i+j)&1) for(int k=1;k<=8;k++) {
                int p=i+dx[k],q=j+dy[k];
                if(check(i,j) && check(p,q)) {
                    flow::make(i*n-n+j,p*n-n+q,1);
                }
            }
        }
    }
    cout<<cnt-flow::solve(n*n+1,n*n+2);
}
原文地址:https://www.cnblogs.com/mollnn/p/12293924.html