[网络流24题] 骑士共存 (二分图)

COGS 746. [网络流24题] 骑士共存

http://www.cogs.pro/cogs/problem/problem.php?pid=746

★★☆   输入文件:knight.in   输出文件:knight.out   简单对比
时间限制:1 s   内存限制:128 MB

骑士共存问题
«问题描述:
在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示。棋盘

上某些方格设置了障碍,骑士不得进入。

«编程任务:
对于给定的n*n个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑
士,使得它们彼此互不攻击。
«数据输入:
由文件knight.in给出输入数据。第一行有2 个正整数n 和m (1<=n<=200, 0<=m<=n*n)
分别表示棋盘的大小和障碍数。接下来的m 行给出障碍的位置。每行2 个正整数,表示障碍的方格坐标。
«结果输出:
将计算出的共存骑士数输出到文件knight.out。
输入文件示例 输出文件示例
knight.in
3 2
1 1

3 3

knight.out

5
最多放置多少个互不攻击的骑士
转化为
最少拿去几个骑士使剩下的骑士互不攻击
最小割
根据红黄格构建二分图
源点向所有红格连流量为1的边
所有黄格向汇点连流量为1的边
能互相攻击的格,通一由红格向黄格连流量为1的边
障碍格不练边
跑最大流
最终格子总数-障碍格-最大流
#include<cstdio>
#include<queue>
using namespace std;
int n,m,tot=1,ans;
int front[40010],to[4000100],nextt[4000100],cap[4000100];
int dx[8]={-2,-2,-1,1,2,2,1,-1};
int dy[8]={-1,1,2,2,1,-1,-2,-2};
int barrier[201][201];
int lev[40010],cur[40010];
int src,decc;
queue<int>q;
void add(int u,int v,int w)
{
    to[++tot]=v;nextt[tot]=front[u];front[u]=tot;cap[tot]=w;
    to[++tot]=u;nextt[tot]=front[v];front[v]=tot;cap[tot]=0;
}
void insert(int x,int y,int tx,int ty)
{
    add((x-1)*n+y,(tx-1)*n+ty,1);
}
bool bfs()
{
    for(int i=0;i<=decc;i++) {lev[i]=-1;cur[i]=front[i];}
    while(!q.empty()) q.pop();
    q.push(src);lev[src]=0;
    while(!q.empty())
    {
        int now=q.front();q.pop();
        for(int i=front[now];i;i=nextt[i])
        {
            int t=to[i];
            if(cap[i]>0&&lev[t]==-1)
            {
                lev[t]=lev[now]+1;
                q.push(t);
                if(t==decc) return true;
            }
        }
    }
    return false;
}
int dinic(int now,int flow)
{
    if(now==decc) return flow;
    int rest=0,delta;
    for(int & i=cur[now];i;i=nextt[i])
    {
        int t=to[i];
        if(lev[t]>lev[now]&&cap[i]>0)
        {
            delta=dinic(t,min(flow-rest,cap[i]));
            if(delta)
            {
                cap[i]-=delta;cap[i^1]+=delta;
                rest+=delta;if(rest==flow) break;
            }
        }
    }
    if(rest!=flow) lev[now]=-1;
    return rest;
}
int main()
{
    /*freopen("knight.in","r",stdin);
    freopen("knight.out","w",stdout);*/
    scanf("%d%d",&n,&m);
    int x,y;decc=n*n+1;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        barrier[x][y]=true;
    }
    for(int i=1;i<=n;i++)
     for(int j=1;j<=n;j++)
      if((i+j)%2) add(src,(i-1)*n+j,1);
      else add((i-1)*n+j,decc,1);
    for(int i=1;i<=n;i++)
     for(int j=1;j<=n;j++)
     {
         if(barrier[i][j]) continue;
         if((i+j)%2)
          for(int k=0;k<8;k++)
               if(i+dx[k]>=1&&i+dx[k]<=n&&j+dy[k]>=1&&j+dy[k]<=n&&!barrier[i+dx[k]][j+dy[k]])
                insert(i,j,i+dx[k],j+dy[k]);
     }
    ans=n*n-m;
    while(bfs()) ans-=dinic(src,4000100); 
    printf("%d",ans);
}
原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/6510080.html