题目描述

在一个 n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示。棋盘上某些方格设置了障碍,骑士不得进入

  

对于给定的 n*n 个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑士,使得它们彼此互不攻击

输入输出格式

输入格式:

第一行有 2 个正整数n 和 m (1<=n<=200, 0<=m<n2),分别表示棋盘的大小和障碍数。接下来的 m 行给出障碍的位置。每行 2 个正整数,表示障碍的方格坐标。

输出格式:

将计算出的共存骑士数输出

输入输出样例

输入样例#1: 复制

3 2
1 1
3 3
输出样例#1: 复制

5 
最大流与最小割之间的转换
最多放多少骑士==最少拿走多少
观察图片不难发现:黄色的不能攻击黄色的,红色同理
那么不难想到二分图匹配
这样就转化成了二分图最小定点覆盖
而二分图最小顶点覆盖==二分图最大匹配。证明可以看[这里](http://www.cnblogs.com/jianglangcaijin/p/6035945.html)
从S向红色连边(权重为1),从红色向能攻击到的黄色连边(权重为INF),从黄色向T连边(权重为1)
 
// luogu-judger-enable-o2
#include<cstdio>
#include<cstring>
#include<queue>
#define AddEdge(x,y,z) add_edge(x,y,z),add_edge(y,x,0);
using namespace std;
const int MAXN=,INF=1e8+;
inline char nc()
{
static char buf[MAXN],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,,MAXN,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
char c=nc();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=nc();}
while(c>=''&&c<=''){x=x*+c-'';c=nc();}
return x*f;
}
int N,M,S,T;
struct node
{
int u,v,flow,nxt;
}edge[MAXN*];
int head[MAXN],cur[MAXN],num=;
inline void add_edge(int x,int y,int z)
{
edge[num].u=x;
edge[num].v=y;
edge[num].flow=z;
edge[num].nxt=head[x];
head[x]=num++;
}
int deep[MAXN];
inline bool BFS()
{
memset(deep,,sizeof(deep));
deep[S]=;
queue<int>q;
q.push(S);
while(q.size()!=)
{
int p=q.front();
q.pop();
for(int i=head[p];i!=-;i=edge[i].nxt)
if(!deep[edge[i].v]&&edge[i].flow)
{
deep[edge[i].v]=deep[p]+;q.push(edge[i].v);
if(edge[i].v==T) return ;
}
}
return deep[T];
}
int DFS(int now,int nowflow)
{
if(now==T||nowflow<=) return nowflow;
int totflow=;
for(int &i=cur[now];i!=-;i=edge[i].nxt)
{
if(deep[edge[i].v]==deep[now]+&&edge[i].flow)
{
int canflow=DFS(edge[i].v,min(nowflow,edge[i].flow));
edge[i].flow-=canflow;edge[i^].flow+=canflow;
totflow+=canflow;
nowflow-=canflow;
if(nowflow<=) break;
}
}
return totflow;
}
int Dinic()
{
int ans=;
while(BFS())
{
memcpy(cur,head,sizeof(head));
ans+=DFS(S,INF);
}
return ans;
}
int a[][],c[][];
int xx[]={,-,-,-,-,+,+,+,+};
int yy[]={,-,-,+,+,+,+,-,-};
int main()
{
#ifdef WIN32
freopen("a.in","r",stdin);
#else
#endif
memset(head,-,sizeof(head));
N=read();M=read();S=;T=N*N+;
for(int i=;i<=M;i++)
{
int x=read(),y=read();
c[x][y]=;
}
for(int i=;i<=N;i++)
for(int j=;j<=N;j++)
a[i][j]=(i-)*N+j;
for(int i=;i<=N;i++)
for(int j=;j<=N;j++)
{
if(c[i][j]) continue;
if((i+j)%)
{
AddEdge(S,a[i][j],);
for(int k=;k<=;k++)
{
int wx=i+xx[k],wy=j+yy[k];
if(wx>=&&wx<=N&&wy>=&&wy<=N)
AddEdge(a[i][j],a[wx][wy],INF);
}
}
else AddEdge(a[i][j],T,);
}
printf("%d",N*N-M-Dinic()); return ;
}
 

洛谷P3355 骑士共存问题的更多相关文章

  1. 2018.08.02 洛谷P3355 骑士共存问题(最小割)

    传送门 这题让我联想到一道叫做方格取数问题的题,如果想使摆的更多,就要使不能摆的更少,因此根据骑士的限制条件建图,求出至少有多少骑士不能摆,减一减就行了. 代码: #include<bits/s ...

  2. 洛谷 [P3355] 骑士共存问题

    二分图求最大独立点集 本问题在二分图中已处理过,此处用dinic写了一遍 #include <iostream> #include <cstdio> #include < ...

  3. 洛谷P3355 骑士共存问题(最小割)

    传送门 de了两个小时的bug愣是没发现错在哪里……没办法只好重打了一遍竟然1A……我有点想从这里跳下去了…… 和方格取数问题差不多,把格子按行数和列数之和的奇偶性分为黑的和白的,可以发现某种颜色一定 ...

  4. 洛谷 P3355 骑士共存问题【最小割】

    同方格取数问题:https://www.cnblogs.com/lokiii/p/8430720.html 记得把障碍点去掉,不连边也不计入sum #include<iostream> # ...

  5. 洛谷P3355 骑士共存问题 二分图_网络流

    Code: #include<cstdio> #include<cstring> #include<queue> #include<vector> #i ...

  6. 洛谷.3355.骑士共存问题(最小割ISAP)

    题目链接 一个很暴力的想法:每个点拆点,向不能同时存在的连边 但是这样边太多了,而且会有很多重复.我不会说我还写了还没过样例 我们实际就是在做一个最大匹配.考虑原图,同在黄/红格里的骑士是互不攻击的, ...

  7. P3355 骑士共存问题

    P3355 骑士共存问题 题目描述 在一个 n*n (n <= 200)个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘上某些方格设置了障碍,骑士不得进入 对于给定的 n*n ...

  8. P3355 骑士共存问题 二分建图 + 当前弧优化dinic

    P3355 骑士共存问题 题意: 也是一个棋盘,规则是“马”不能相互打到. 思路: 奇偶点分开,二分图建图,这道题要注意每个点可以跑八个方向,两边都可以跑,所以边 = 20 * n * n. 然后di ...

  9. P3355 骑士共存问题 网络流

    骑士共存 题目描述 在一个 n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘上某些方格设置了障碍,骑士不得进入 对于给定的 n*n 个方格的国际象棋棋盘和障碍标志,计算棋盘上最 ...

随机推荐

  1. java流与文件的操作 文件加密

    课后作业 1,源代码 import java.io.*; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttribu ...

  2. 比较排序算法(PHP)

    冒泡排序 两两比较相邻记录的关键字,如果反序则交换,大的数字往下沉,一直到最大的出现在数组最后 function swap(&$x, &$y) { $temp = $x; $x = $ ...

  3. Linux初学习

    Linux Linux运行与关闭 Linux 是一套免费使用和自由传播的类 Unix 操作系统,是一个基于 POSIX 和 UNIX 的多用户.多任务.支持多线程和多 CPU 的操作系统. Linux ...

  4. js php 数组比較

    php 与 javascript 数组除了定义以及 操作上有非常大的差别,还有非常多其他的差别.如今我们就来讨论讨论.    1.大家都知道php比較两个数组是否全相等(值,索引)相等 $a=arra ...

  5. 聊聊高并发(四十四)解析java.util.concurrent各个组件(二十) Executors工厂类

    Executor框架为了更方便使用,提供了Executors这个工厂类.通过一系列的静态工厂方法.能够高速地创建对应的Executor实例. 仅仅有一个nThreads參数的newFixedThrea ...

  6. HTML5_Web_SQL_Database数据库

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAiEAAAEGCAIAAAA8NNLDAAAgAElEQVR4nOxdd5hcVdk/SUgghCSEhC ...

  7. ListView实现丰富的列表功能

    ListView实现丰富的列表功能 1.主布局activity_main.xml <?xml version="1.0" encoding="utf-8" ...

  8. sublime text3 3143注册码

    注册码: -– BEGIN LICENSE -– TwitterInc 200 User License EA7E-890007 1D77F72E 390CDD93 4DCBA022 FAF60790 ...

  9. windows下git的安装和使用

    git到底是个什么东西,我这里就不介绍了,如果大家还有不懂的,可以去百度一下的.我这里给一个介绍的网址:git简介        这里在留一个地址http://baike.baidu.com/subv ...

  10. 详细图解mongodb下载、安装、配置与使用

    记得在管理员模式下运行CMD,否则服务将启动失败 转载:http://blog.csdn.net/boby16/article/details/51221474 详细图解,记录 win7 64 安装m ...