骑士共存问题

网格中的网络流问题。在网格中的问题很容易就想到黑白染色。将棋盘黑白染色,把可用的黑格和能攻击到的可用的白格连起来,转化为二分图最大独立集问题,最大流搞一波。

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int S=0,T=40005,inf=0x7f7f7f7f;
bool g[205][205];
int n,m,ecnt=1,h[T<<2],head[T<<2];
struct Edge {
    int to,nxt,val;
} e[T<<4];
void add(int x,int y,int val) {
    e[++ecnt].to=y,e[ecnt].nxt=head[x],e[ecnt].val=val,head[x]=ecnt;
    e[++ecnt].to=x,e[ecnt].nxt=head[y],e[ecnt].val=0,head[y]=ecnt;
}
bool bfs() {
    memset(h,-1,sizeof h);
    queue<int>q;
    q.push(0);
    h[0]=0;
    while(!q.empty()) {
        int u=q.front();
        q.pop();
        for(int i=head[u]; i; i=e[i].nxt) {
            int v=e[i].to;
            if(h[v]==-1&&e[i].val) {
                h[v]=h[u]+1;
                q.push(v);
            }
        }
    }
    return h[T]!=-1;
}
int dfs(int x,int f) {
    if(x==T)return f;
    int used=0,tp;
    for(int i=head[x]; i; i=e[i].nxt) {
        int v=e[i].to;
        if(h[v]-1==h[x]&&e[i].val) {
            tp=dfs(v,min(e[i].val,f-used));
            used+=tp;
            e[i].val-=tp;
            e[i^1].val+=tp;
            if(used==f)return f;
        }
    }
    if(used==0)h[x]=-1;
    return used;
}
int maxflow;
void dinic() {
    maxflow=0;
    while(bfs()) {
        maxflow+=dfs(0,inf);
    }
}
int main() {
    cin>>n>>m;
    for(int i=1; i<=m; i++) {
        int a,b;
        scanf("%d%d",&a,&b);
        g[a][b]=1;
    }
    for(int i=1; i<=n; i++) {//建图,代码打的好冗杂啊。。。
        for(int j=1; j<=n; j++) {
            if(!g[i][j]) {
                if(((i+j)&1)==0)add(S,(i-1)*n+j,1);
                else add((i-1)*n+j,T,1);
            }
            if(((i+j)&1)==0&&!g[i][j]) {
                if(i-2>0&&j-1>0)if(!g[i-2][j-1])add((i-1)*n+j,(i-3)*n+j-1,inf);
                if(i-2>0&&j+1<=n)if(!g[i-2][j+1])add((i-1)*n+j,(i-3)*n+j+1,inf);
                if(i-1>0&&j+2<=n)if(!g[i-1][j+2])add((i-1)*n+j,(i-2)*n+j+2,inf);
                if(i-1>0&&j-2>0)if(!g[i-1][j-2])add((i-1)*n+j,(i-2)*n+j-2,inf);
                if(i+2<=n&&j-1>0)if(!g[i+2][j-1])add((i-1)*n+j,(i+1)*n+j-1,inf);
                if(i+2<=n&&j+1<=n)if(!g[i+2][j+1])add((i-1)*n+j,(i+1)*n+j+1,inf);
                if(i+1<=n&&j-2>0)if(!g[i+1][j-2])add((i-1)*n+j,i*n+j-2,inf);
                if(i+1<=n&&j+2<=n)if(!g[i+1][j+2])add((i-1)*n+j,i*n+j+2,inf);
            }
        }
    }
    dinic();
    cout<<n*n-m-maxflow;
}
    原文作者:骑士周游问题
    原文地址: https://blog.csdn.net/superdata999/article/details/80033862
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞