洛谷.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> # ...
随机推荐
- STOMP Over WebSocket
Show Table of Contents What is STOMP? STOMP is a simple text-orientated messaging protocol. It defin ...
- eclipse中运行项目出现空白错误提示解决办法
别人所给出的解决办法:https://blog.csdn.net/fzdg2019/article/details/79384539 两个办法: 方法一:配置环境变量 方法二:修改eclipse安装目 ...
- centos下编译安装mysql5.5/5.6/5.7
2018-12-28 14:38:46 星期五 centos 系统在mysql官网, 按照教程去配置yum源, 然后安装, 不用自己找依赖了: https://dev.mysql.com/doc/my ...
- tomcat8配置SSL
参考网址:http://www.micmiu.com/enterprise-app/sso/sso-cas-sample/#viewSource 1.生成证书 keytool -genkey -ali ...
- [How to]HBase集群备份方法--Replication机制
1.简介 HBase备份的方法在[How to]HBase集群备份方法文章中已经有些介绍,但是这些方法都不是HBase本身的特性在支持,都是通过MR计算框架结合HBase客户端的方式,或者直接拷贝HB ...
- javascript 类型比较方法
不要使用new Number().new Boolean().new String()创建包装对象: 用parseInt()或parseFloat()来转换任意类型到number: 用String() ...
- winform(记事本--剪切复制等和打开)
- Deep Learning系统实训之三:卷积神经网络
边界填充(padding):卷积过程中,越靠近图片中间位置的像素点越容易被卷积计算多次,越靠近边缘的像素点被卷积计算的次数越少,填充就是为了使原来边缘像素点的位置变得相对靠近中部,而我们又不想让填充的 ...
- Hibrenate关系映射(一对一外键关联)
一.一对一(单向):使用外部索引将其中的一个类作为parent,相对应的一个就是子类,并且参照父 类的主键ID来生成数据库表.(比如:可以将husband中设置一个wife_id对应wife中的主键i ...
- python 全栈开发,Day60(MySQL的前戏,数据库概述,MySQL安装和基本管理,初识MySQL语句)
一.MySQL的前戏 在学习Mysql之前,我们先来想一下一开始做的登录注册案例,当时我们把用户的信息保存到一个文件中: #用户名 |密码 root|123321 alex|123123 上面文件内容 ...