【luogu 3355】骑士共存问题

题目描述
在一个 n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示。
《【luogu 3355】骑士共存问题》
棋盘上某些方格设置了障碍,骑士不得进入
对于给定的 n*n 个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑士,使得它们彼此互不攻击
输入格式:
第一行有 2 个正整数n 和 m (1<=n<=200, 0<=m

#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
#define S 40003
#define T 40002
using namespace std;
struct node{
    int to,next,flow,from;
}ed[1000100];
int head[41000],deep[41000],size=-1,ind[210][210],curr[41000],max_flow,n,m,k;
int dx[]={1,1,-1,-1,2,2,-2,-2};
int dy[]={2,-2,2,-2,1,-1,1,-1};
int vis[210][210];
void add(int from,int to,int flow)
{
    size++;
    ed[size].to=to;
    ed[size].from=from;
    ed[size].flow=flow;
    ed[size].next=head[from];
    head[from]=size;
}
bool bfs()
{
    queue <int> q;
    memset(deep,0,sizeof(deep));
    q.push(S);
    deep[S]=1;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        if(u==T) return true;
        for(int i=head[u];~i;i=ed[i].next)
        {
            int v=ed[i].to;
            if(!deep[v]&&ed[i].flow)
            {
                q.push(v);
                deep[v]=deep[u]+1;
            }
        }
    }
    return false;
}
int dfs(int u,int cur)
{
    int rest=cur;
    if(u==T) return cur;
    for(int i=curr[u];~i;i=ed[i].next)
    {
        int v=ed[i].to;
        if(deep[v]==deep[u]+1&&ed[i].flow)
        {
            int new_flow=dfs(v,min(rest,ed[i].flow));
            ed[i].flow-=new_flow;
            ed[i^1].flow+=new_flow;
            rest-=new_flow;
            if(ed[i].flow) curr[u]=i;
            if(!rest) break;
        }
    }
    if(cur==rest) deep[u]=-1;
    return cur-rest;
}
int dinic()
{
    while(bfs())
    {
        for(int i=0;i<=40010;i++) curr[i]=head[i];
        max_flow+=dfs(S,1e9);
    }
    return max_flow;
}
int main()
{
    memset(head,-1,sizeof(head));
    int cnt=0;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            ind[i][j]=++cnt;
    for(int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        vis[x][y]=1;
    }
    for(int x=1;x<=n;x++)
    {
        for(int y=1;y<=n;y++)
        {
            if(vis[x][y]) continue;
            if(((x+y)%2)==0)
            {
                for(int k=0;k<8;k++)
                {   
                    int tx=x+dx[k];
                    int ty=y+dy[k];
                    if(tx<1||tx>n||ty<1||ty>n) continue;
                    add(ind[x][y],ind[tx][ty],1e9);
                    add(ind[tx][ty],ind[x][y],0);
                }
            }
        }
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            if(vis[i][j]) continue;
            if(((i+j)%2)==0) add(S,ind[i][j],1),add(ind[i][j],S,0);
            else add(ind[i][j],T,1),add(T,ind[i][j],0);
        }
    printf("%d",n*n-dinic()-m);
    return 0;
}
    原文作者:骑士周游问题
    原文地址: https://blog.csdn.net/DT_Kang/article/details/79653110
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞