洛谷.3355.骑士共存问题(最小割ISAP)
一个很暴力的想法:每个点拆点,向不能同时存在的连边
但是这样边太多了,而且会有很多重复。我不会说我还写了还没过样例
我们实际就是在做一个最大匹配。考虑原图,同在黄/红格里的骑士是互不攻击的,即不会连边。
那么拿这两部分建二分图,分别连向S,T。障碍直接不参与连边。这样边数也少 也直观好写。
原问题尽可能保留多等价于尽可能移走少。求最小割即可。
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
#define ID(x,y) (((x)-1)*n+(y))
const int N=40010,M=N<<3,INF=0x3f3f3f3f,MAXIN=1e5;
int n,m,src,des,Enum,cur[N],H[N],nxt[M<<1],fr[M<<1],to[M<<1],cap[M<<1],q[N],lev[N],num[N],pre[N],id[N][N];
bool Map[203][203],cant[N];
char IN[MAXIN],*SS=IN,*TT=IN;
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline void AddEdge(int u,int v,int w)
{
if(!cant[u] && !cant[v])
to[++Enum]=v, fr[Enum]=u, nxt[Enum]=H[u], cap[Enum]=w, H[u]=Enum,
to[++Enum]=u, fr[Enum]=v, nxt[Enum]=H[v], cap[Enum]=0, H[v]=Enum;
}
bool BFS()
{
for(int i=src; i<=des; ++i) lev[i]=des+1;
lev[des]=0, q[0]=des;
int h=0,t=1;
while(h<t)
{
int x=q[h++];
for(int i=H[x]; i; i=nxt[i])
if(cap[i^1] && lev[to[i]]==des+1)
lev[to[i]]=lev[x]+1, q[t++]=to[i];
}
return lev[src]<=des;
}
int Augment()
{
for(int i=des; i!=src; i=fr[pre[i]])
--cap[pre[i]], ++cap[pre[i]^1];
return 1;
}
int ISAP()
{
if(!BFS()) return 0;
for(int i=src; i<=des; ++i) ++num[lev[i]],cur[i]=H[i];
int res=0,x=src;
while(lev[src]<=des)
{
if(x==des) res+=Augment(),x=src;
bool can=0;
for(int i=cur[x]; i; i=nxt[i])
if(lev[to[i]]==lev[x]-1 && cap[i])
{
can=1, cur[x]=i, pre[x=to[i]]=i;
break;
}
if(!can)
{
int mn=des;
for(int i=H[x]; i; i=nxt[i])
if(cap[i]) mn=std::min(mn,lev[to[i]]);
if(!--num[lev[x]]) break;
++num[lev[x]=mn+1];
cur[x]=H[x];
if(x!=src) x=fr[pre[x]];
}
}
return res;
}
int main()
{
n=read(),m=read();
Enum=1, src=0, des=n*n+1;
for(int u,v,i=1; i<=m; ++i)
u=read(),v=read(),Map[u][v]=cant[ID(u,v)]=1;
for(int now,i=1; i<=n; ++i)
for(int j=1; j<=n; ++j)
if(!Map[i][j])
if((i+j)&1)//红格
AddEdge(ID(i,j),des,1);
else
{
now=ID(i,j), AddEdge(src,now,1);
if(i>2){//用for写?无所谓了~~其实是我忘了~~
if(j>1) AddEdge(now,ID(i-2,j-1),INF);
if(j<n) AddEdge(now,ID(i-2,j+1),INF);
}
if(i>1){
if(j>2) AddEdge(now,ID(i-1,j-2),INF);
if(j+1<n) AddEdge(now,ID(i-1,j+2),INF);
}
if(i+1<n){
if(j>1) AddEdge(now,ID(i+2,j-1),INF);
if(j<n) AddEdge(now,ID(i+2,j+1),INF);
}
if(i<n){
if(j>2) AddEdge(now,ID(i+1,j-2),INF);
if(j+1<n) AddEdge(now,ID(i+1,j+2),INF);
}
}
printf("%d",n*n-m-ISAP());
return 0;
}
洛谷.3355.骑士共存问题(最小割ISAP)的更多相关文章
- 洛谷P3355 骑士共存问题(最小割)
传送门 de了两个小时的bug愣是没发现错在哪里……没办法只好重打了一遍竟然1A……我有点想从这里跳下去了…… 和方格取数问题差不多,把格子按行数和列数之和的奇偶性分为黑的和白的,可以发现某种颜色一定 ...
- 洛谷P3355 骑士共存问题
题目描述 在一个 n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘上某些方格设置了障碍,骑士不得进入 对于给定的 n*n 个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置 ...
- [洛谷]P3729 曼哈顿计划EX(最小割树/等价流树)
题目大意:给出一张n个点m条边的无向图,每个点有点权,q次询问,每次给出k,要求选出若干个点点权之和不小于k,求一个最大的值x,使得选出的点中任意两点之间至少有x条互不相交的链.(n<=550, ...
- 洛谷 P3227 [HNOI2013]切糕(最小割)
题解 Dinic求最小割 题目其实就是求最小的代价使得每个纵轴被分成两部分 最小割!!! 我们把每个点抽象成一条边,一个纵轴就是一条\(S-T\)的路径 但是题目要求\(|f(x,y)-f(x',y' ...
- bzoj 2039 & 洛谷 P1791 人员雇佣 —— 二元关系最小割
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2039 https://www.luogu.org/problemnew/show/P1791 ...
- 洛谷P2046 [NOI2010]海拔(最小割,平面图转对偶图)
传送门 不明白为什么大佬们一眼就看出这是最小割…… 所以总而言之这就是一个最小割我也不知道为什么 然后边数太多直接跑会炸,所以要把平面图转对偶图,然后跑一个最短路即可 至于建图……请看代码我实在无能为 ...
- P3355 骑士共存问题 (最小割)
题意:nxn的棋盘 有m个坏点 求能在棋盘上放多少个马不会互相攻击 题解:这个题仔细想想居然和方格取数是一样的!!! 每个马他能攻击到的地方的坐标 (x+y)奇偶性不一样 于是就黑白染色 s-> ...
- 2018.08.02 洛谷P3355 骑士共存问题(最小割)
传送门 这题让我联想到一道叫做方格取数问题的题,如果想使摆的更多,就要使不能摆的更少,因此根据骑士的限制条件建图,求出至少有多少骑士不能摆,减一减就行了. 代码: #include<bits/s ...
- 洛谷 P3355 骑士共存问题【最小割】
同方格取数问题:https://www.cnblogs.com/lokiii/p/8430720.html 记得把障碍点去掉,不连边也不计入sum #include<iostream> # ...
随机推荐
- STM32F103X datasheet学习笔记---Flexible static memory controller (FSMC)
1.前言 FSMC模块能够与同步或异步存储器和16位PC存储器卡接口,它的主要作用是: 将AHB传输信号转换到适当的外部设备协议 满足访问外部设备的时序要求 所有的外部存储器共享控制器输出的地址.数据 ...
- java web path
1,request.getRealPath("/");这个方法已不推荐用 2,在Servlet 里用this.getServletContext().getRealPath(&qu ...
- 源码编译安装mysql5.5.33
源码编译安装mysql5.5.33 一.安装cmake编译工具 跨平台编译器 # yum install -y gcc* # yum install -y cmake 解决依赖关系 # yum ins ...
- 转载:Nginx是什么(1.1)《深入理解Nginx》(陶辉)
原文:https://book.2cto.com/201304/19609.html 人们在了解新事物时,往往习惯通过类比来帮助自己理解事物的概貌.那么,我们在学习Nginx时也采用同样的方式,先来看 ...
- 内存分配方式,堆区,栈区,new/delete/malloc/free
1.内存分配方式 内存分配方式有三种: [1]从静态存储区域分配.内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量,static变量. [2]在栈上创建.在执行函数时 ...
- Go语言学习之路(持续更新中)
菜鸟 Go语言教程 教程(RUNOOB.COM):http://www.runoob.com/go/go-tutorial.html Go全球官网:https://golang.org/ (2018- ...
- Java桌面程序打包成exe可执行文件
前言: 我们都知道Java可以将二进制程序打包成可执行jar文件,双击这个jar和双击exe效果是一样一样的,但感觉还是不同.其实将java程序打包成exe也需要这个可执行jar文件. 准备: ecl ...
- vue2的缓存问题(非原创)
keep-alive是vue内置的一个组件,可以使被它包含的组件处于保留状态,或避免被重新渲染. 用法: 运行结果描述: input输入框内,路由切换输入框内部的内容不会发生改变. 常见的用法:(下图 ...
- Slick.js+Animate.css 结合让网页炫动起来
一个代码示例: html部分 <link rel='stylesheet prefetch' href='//cdnjs.cloudflare.com/ajax/libs/animate.css ...
- vmware+CentOs 6.9的安装步骤
一.安装步骤 linux分区 登录用户名和密码 登录用户名和密码后安装成功 二.远程控制Xshell的安装