#网络流,最大流,dinic#洛谷 3355 骑士共存问题

题目

在棋盘内放入尽量多的骑士,使他们(马步)互不攻击。


分析

匈牙利算法
但是这次要用网络流最大流,dinic。


代码

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <queue>
using namespace std;
struct node{int y,next,w;}e[500001];
bool v[203][203]; int ls[50001],dis[50001],n,m,ans;
const int dx[8]={1,1,-1,-1,2,2,-2,-2},dy[8]={2,-2,2,-2,1,-1,1,-1};
int in(){
    int ans=0; char c=getchar();
    while (!isdigit(c)) c=getchar();
    while (isdigit(c)) ans=ans*10+c-48,c=getchar();
    return ans;
}
void add(int x,int y){
    e[++m].y=y; e[m].w=1; e[m].next=ls[x]; ls[x]=m;
    e[++m].y=x; e[m].w=0; e[m].next=ls[y]; ls[y]=m;
}
bool bfs(){
    for (int i=1;i<=n*n+2;i++) dis[i]=0;
    dis[n*n+1]=1; queue<int>q; q.push(n*n+1);
    while (q.size()){
        int x=q.front(); q.pop();
        for (int i=ls[x];i;i=e[i].next)
        if (e[i].w>0&&!dis[e[i].y]){
            dis[e[i].y]=dis[x]+1;
            if (e[i].y==n*n+2) return 1;
            q.push(e[i].y);
        }
    }
    return 0;
}
int dfs(int x,int flow)
{
    if(x==n*n+2||!flow) return flow;
    int rest=0,f;
    for(int i=ls[x];i;i=e[i].next)
    {
        int y=e[i].y;
        if(dis[x]+1==dis[y]&&e[i].w)
        {
            rest+=(f=dfs(y,min(flow-rest,e[i].w)));
            e[i].w-=f;e[i^1].w+=f;
        }
    }
    if(!rest) dis[x]=0;
    return rest;
}
int main(){
    n=in(); m=in(); ans=n*n-m;
    while (m--) v[in()][in()]=1; m=1;
    for (int i=1;i<=n;i++)
    for (int j=1;j<=n;j++)
    if (!v[i][j]){
        if (!((i+j)&1)){
        add(n*n+1,(i-1)*n+j);
        for (int k=0;k<8;k++){
            int x=i+dx[k],y=j+dy[k];
            if (v[x][y]||x<1||x>n||y<1||y>n) continue;
            add((i-1)*n+j,(x-1)*n+y); 
        }
        }else add((i-1)*n+j,n*n+2);
    }
    while (bfs()) ans-=dfs(n*n+1,1e7);
    return !printf("%d",ans);
}

猜你喜欢

转载自blog.csdn.net/sugar_free_mint/article/details/80770592