[网络流24题] 骑士共存

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

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

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

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

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

3 3

knight.out

5

【题解】:

首先把棋盘黑白染色,使相邻格子颜色不同。把所有可用的黑色格子看做二分图X集合中顶点,可用的白色格子看做Y集合顶点。从S向X集合中每个点连接一条容量为1的有向边,从Y集合中每个点向T连接一条容量为1的有向边。从每个可用的黑色格子向骑士一步能攻击到的可用的白色格子连接一条容量为无穷大的有向边。求最小割,结果就是可用格子的数量减去最小割。

【代码】:

#include<cstdio>
#include<iostream>
using namespace std;
const int dx[]={1,1,2,2,-1,-1,-2,-2};
const int dy[]={2,-2,1,-1,2,-2,1,-1};
const int N=210;
const int M=N*N;
const int inf=0x3f3f3f3f;
int n,m,S,T,num,id[N][N],mp[N][N],head[M],dis[M],q[M*5];
struct node{
    int v,next,cap;
}e[M*10];int tot=1;
void add(int x,int y,int z){
    e[++tot].v=y;e[tot].cap=z;e[tot].next=head[x];head[x]=tot;
    e[++tot].v=x;e[tot].cap=0;e[tot].next=head[y];head[y]=tot;
}
bool bfs(){
    for(int i=S;i<=T;i++) dis[i]=inf;
    int h=0,t=1;
    q[t]=S;dis[S]=0;
    while(h!=t){
        int x=q[++h];
        for(int i=head[x];i;i=e[i].next){
            int v=e[i].v;
            if(e[i].cap&&dis[v]>dis[x]+1){
                dis[v]=dis[x]+1;
                if(v==T) return 1;
                q[++t]=v;
            }
        }
    }
    return dis[T]<inf;
}
int dfs(int x,int f){
    if(x==T) return f;
    int used=0,t;
    for(int i=head[x];i;i=e[i].next){
        int v=e[i].v;
        if(e[i].cap&&dis[v]==dis[x]+1){
            t=dfs(v,min(f,e[i].cap));
            //if(!t) dis[t]=0;//TLE*1
            e[i].cap-=t;e[i^1].cap+=t;
            f-=t;used+=t;
            if(!f) return used;
        }
    }
    dis[x]=0;//TLE*2
    return used;
}
int dinic(){
    int res=0;
    while(bfs()) res+=dfs(S,inf);
    return n*n-m-res;
}
void mapping(){
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            id[i][j]=++num;
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(mp[i][j]) continue;
            if((i+j)&1^1){//黑
                add(S,id[i][j],1);
                for(int k=0;k<8;k++){
                    int nx=i+dx[k],ny=j+dy[k];
                    if(nx<1||nx>n||ny<1||ny>n||mp[nx][ny]) continue;
                    add(id[i][j],id[nx][ny],1);
                }
            }
            else{//白
                add(id[i][j],T,1);
            }
        }
    }
}
int main(){
    freopen("knight.in","r",stdin);
    freopen("knight.out","w",stdout);
    scanf("%d%d",&n,&m);S=0;T=n*n+1;
    for(int i=1,x,y;i<=m;i++) scanf("%d%d",&x,&y),mp[x][y]=1;
    mapping();
    printf("%d",dinic());
    return 0;
} 

 

 

 

时间: 12-06

[网络流24题] 骑士共存的相关文章

AC日记——[网络流24题]骑士共存 cogs 746

746. [网络流24题] 骑士共存 ★★☆   输入文件:knight.in   输出文件:knight.out   简单对比时间限制:1 s   内存限制:128 MB 骑士共存问题 «问题描述: 在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘 上某些方格设置了障碍,骑士不得进入. «编程任务: 对于给定的n*n个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑 士,使得它们彼此互不攻击. «数据输入: 由文件knight.in给出输入数据.第一行

[COGS746] [网络流24题] 骑士共存

★★☆   输入文件:knight.in   输出文件:knight.out   简单对比 时间限制:1 s   内存限制:128 MB 骑士共存问题 «问题描述: 在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘 上某些方格设置了障碍,骑士不得进入. «编程任务: 对于给定的n*n个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑 士,使得它们彼此互不攻击. «数据输入: 由文件knight.in给出输入数据.第一行有2 个正整数n 和m (1<=n<

[网络流24题] 骑士共存(cogs 746)

骑士共存问题?问题描述:在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘 上某些方格设置了障碍,骑士不得进入. ?编程任务:对于给定的n*n个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑士,使得它们彼此互不攻击.?数据输入:由文件knight.in给出输入数据.第一行有2 个正整数n 和m (1<=n<=200, 0<=m<=n*n)<n2),< span="">分别表示棋盘的大小和障碍数.接下来的

[网络流24题] 骑士共存问题

题面: 传送门 思路: 基本上和方格取数问题差不多 这道题可以证明,如果把每两个不能共存的点连在一起,那么这个图没有奇环,是一个二分图 同时,如果把这个图像国际象棋一样黑白染色,那么连边的两个点颜色不同 源点连黑点,边权为1 黑点连白点,边权为inf 白点连汇点,边权为1 跑出最大流,即为这个图的最小点覆盖 用整张图的点数减去障碍物数量,再减去最大流的值就是答案了 Code: 1 #include<iostream> 2 #include<cstdio> 3 #include<

【网络流24题】骑士共存问题(最大流)

[网络流24题]骑士共存问题(最大流) 题面 Cogs 题解 这题本质上和方格取数问题没有任何区别 首先也是可以黑白染色 因为马必定会跳到异色点上面去 然后同样的,源点向一种颜色,另一种颜色向汇点连边 因为代价就是1,所以容量都是1 这里考虑的"相邻"的情况是马的跳法 因此,枚举从当前点能够到达的位置,连一条容量为INF的边过去 障碍直接特殊考虑就行了 最后的答案就是所有可以放的位置数减去最大流(最小割) #include<iostream> #include<cst

「网络流24题」 题目列表

「网络流24题」 题目列表 序号 题目标题 模型 题解 1 飞行员配对方案问题 二分图最大匹配 <1> 2 太空飞行计划问题 最大权闭合子图 <2> 3 最小路径覆盖问题 二分图最小路径覆盖 <3> 4 魔术球问题 <4> 5 圆桌问题 <5> 6 最长递增子序列问题 <6> 7 试题库问题 <7> 8 机器人路径规划问题 <8> 9 方格取数问题 二分图最大点权独立集 <9> 10 餐巾计划问题

网络流24题 部分总结

网络流24题 部分总结 慢慢写吧... 以前做过一些了: 然后发现也做了不少了,集中写一下. 警告: 题目按照随机顺序排列. 文章中只有建模的方法. 最小路径覆盖问题 http://cogs.pro:8080/cogs/problem/problem.php?pid=728 题目即题解... // It is made by XZZ #include<cstdio> #include<algorithm> #include<cstring> #define File #

网络流24题小结

网络流24题 前言 网络流的实战应用篇太难做了,因此先完善这一部分 ## 第一题:飞行员配对方案 \(BSOJ2542\)--二分图 最优匹配 题意 两国飞行员\(x\)集合\(y\)集合,\(x\)飞行员可以配对特定的\(y\)集合的飞行员(可无),求一对一配对最大数 Solution 二分图最大匹配裸题,最大流实现 建图:(设\(i\in x\)而\(i'\in y\)) \((S,i,1)~(i',T,1)\) 对\((i,j')\)可匹配\((i,j',1)\) Code 略 ## 第二

【网络流24题----14】孤岛营救问题

孤岛营救问题 Time Limit: 1 Sec  Memory Limit: 128 MB Description 1944年,特种兵麦克接到国防部的命令.要求马上赶赴太平洋上的一个孤岛,营救被敌军俘虏的大兵瑞恩.瑞恩被关押在一个迷宫里,迷宫地形复杂,但幸好麦克得到了迷宫的地形图.迷宫的外形是一个长方形,其南北方向被划分为 N行,东西方向被划分为 M列,于是整个迷宫被划分为 N×M个单元.每个单元的位置可用一个有序数对 (单元的行号,单元的列号)来表示.南北或东西方向相邻的 2个单元之间可能互