P3355 骑士共存问题题解
题目链接:P3355 骑士共存问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题解:
棋盘问题考虑黑白染色成为二分图后做。
观察马的性质,可知一个点只能到一个异色点,所以,构造方案可以先将所有同色点放上马,再考虑有那些异色点不可以放置。
方法一:
网络流,时间复杂度为O(|E|min(|E|0.5,|V|0.3))
从源点向每个白点连一条限制为1的边(黑色,白色都可以我选定先在白色放满马)(这里的1没有太大的意义,可以理解为每个点一匹马)
从白点向与它不可共存的点,连边,限制为1因为流量最大为1。
从黑点向汇点连一条限制为1的边。
最后答案为n*n-m-ans,表示总点数减去障碍点,再减去冲突的黑点。
#include <bits/stdc++.h>
using namespace std;
const int N=50010;
const int M=500010;
int tot=1,n,m,s,t,nxt[M],go[M],hd[N],dep[N],cur[N],vis[N],jz[M],ans;
queue<int> q;
bool bfs()
{
memset(dep,0,sizeof(dep));
memcpy(cur,hd,sizeof(hd));
q.push(s);
dep[s]=1;
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=hd[u];i;i=nxt[i])
{
int v=go[i];
if(!jz[i]||dep[v])continue;
dep[v]=dep[u]+1;
q.push(v);
}
}
return dep[t];
}
int dfs(int u,int flow)
{
if(u==t)return flow;
int out=0;
for(int i=cur[u];i&&flow;i=nxt[i])
{
cur[u]=i;
int v=go[i];
if(jz[i]&&dep[v]==dep[u]+1)
{
int res=dfs(v,min(jz[i],flow));
if(res)
{
jz[i]-=res;jz[i^1]+=res;flow-=res;out+=res;
}
}
}
if(out==0) dep[u]=0;
return out;
}
void add(int u,int v,int w)
{
nxt[++tot]=hd[u];
hd[u]=tot;
go[tot]=v;
jz[tot]=w;
}
int id(int x,int y)
{
return (x-1)*n+y;
}
int xj[10]={2,2,-2,-2,1,1,-1,-1};
int yj[10]={1,-1,1,-1,2,-2,2,-2};
int main()
{
scanf("%d%d",&n,&m);
s=0,t=n*n+1;
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
vis[id(x,y)]=1;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
int ids=id(i,j);
if(vis[ids])continue;
if((i+j)%2==0)
{
add(s,ids,1);
add(ids,s,0);
for(int k=0;k<8;k++)
{
int x=i+xj[k];
int y=j+yj[k];
if(x>0&&y>0&&x<=n&&y<=n&&vis[id(x,y)]==0)
{
add(ids,id(x,y),1e9);
add(id(x,y),ids,0);
}
}
}
else
{
add(ids,t,1);
add(t,ids,0);
}
}
while(bfs())
ans+=dfs(s,1e9);
printf("%lld\n",n*n-m-ans);
return 0;
}
方法二:
匈牙利算法。
从白点向限制的黑点连边,跑匈牙利,求最大匹配。
但是加了一个数据,匈牙利跑不过去,所以二分图的问题,最好转成网络流来做,更快。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=50010;
const int M=500010;
int tot,n,m,nxt[M],go[M],hd[N],girl[N],ans,wz[210][210];
bool bk[N],vis[N];
int xj[10]={2,2,-2,-2,1,1,-1,-1};
int yj[10]={1,-1,1,-1,2,-2,2,-2};
inline int read(){
int ans=0;char c;bool flag=true;
for(;c<'0'||c>'9';c=getchar())if(c=='-')flag=false;
for(;c>='0'&&c<='9';c=getchar())ans=ans*10+c-'0';
return flag ? ans : -ans;
}
inline void add(int x,int y)
{
nxt[++tot]=hd[x];go[tot]=y;hd[x]=tot;
return ;
}
inline bool find(int x)
{
for(int i=hd[x];i;i=nxt[i])
{
int y=go[i];
if(vis[y])continue;
vis[y]=1;
if(!girl[y]||find(girl[y]))
{
girl[y]=x;
return 1;
}
}
return 0;
}
inline int id(int x,int y)
{
return (x-1)*n+y;
}
int main()
{
n=read(),m=read();
for(int i=1;i<=m;i++)
{
int x,y;
x=read(),y=read();
bk[id(x,y)]=1;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
wz[i][j]=id(i,j);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(bk[wz[i][j]])continue;
if((i+j)%2)
for(int k=0;k<8;k++)
{
int x=i+xj[k];
int y=j+yj[k];
if(x>0&&y>0&&x<=n&&y<=n&&bk[wz[x][y]]==0)
add(wz[i][j],wz[x][y]);
} }
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if((i+j)%2&&!bk[wz[i][j]])
{
memset(vis,0,sizeof(vis));
if(find(wz[i][j]))ans++;
}
printf("%d\n",n*n-m-ans);
return 0;
}
P3355 骑士共存问题题解的更多相关文章
- P3355 骑士共存问题
P3355 骑士共存问题 题目描述 在一个 n*n (n <= 200)个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘上某些方格设置了障碍,骑士不得进入 对于给定的 n*n ...
- P3355 骑士共存问题 二分建图 + 当前弧优化dinic
P3355 骑士共存问题 题意: 也是一个棋盘,规则是“马”不能相互打到. 思路: 奇偶点分开,二分图建图,这道题要注意每个点可以跑八个方向,两边都可以跑,所以边 = 20 * n * n. 然后di ...
- 网络流棋盘模型 | P3355 骑士共存问题 P4304 [TJOI2013]攻击装置
题面(骑士共存问题) 在一个 \(n \times n\) 个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘上某些方格设置了障碍,骑士不得进入. 对于给定的 \(n \times n ...
- P3355 骑士共存问题 网络流
骑士共存 题目描述 在一个 n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘上某些方格设置了障碍,骑士不得进入 对于给定的 n*n 个方格的国际象棋棋盘和障碍标志,计算棋盘上最 ...
- 洛谷P3355 骑士共存问题
题目描述 在一个 n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘上某些方格设置了障碍,骑士不得进入 对于给定的 n*n 个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置 ...
- P3355 骑士共存问题【洛谷】(二分图最大独立集变形题) //链接矩阵存图
展开 题目描述 在一个 n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘上某些方格设置了障碍,骑士不得进入 对于给定的 n*n 个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可 ...
- 2018.08.02 洛谷P3355 骑士共存问题(最小割)
传送门 这题让我联想到一道叫做方格取数问题的题,如果想使摆的更多,就要使不能摆的更少,因此根据骑士的限制条件建图,求出至少有多少骑士不能摆,减一减就行了. 代码: #include<bits/s ...
- 【Luogu】P3355骑士共存问题(最小割)
题目链接 像题面那样把棋盘染成红黄点.发现骑士迈一步能到达的点的颜色一定是跟他所在的格子的颜色不同的.于是(woc哪来的于是?这个性质有这么明显吗?)从源点向所有红点连边,从所有黄点向汇点连边,红点向 ...
- LUOGU P3355 骑士共存问题(二分图最大独立集)
传送门 因为骑士只能走"日"字,所以一定是从一个奇点到偶点或偶点到奇点,那么这就是一张二分图,题目要求的其实就是二分图的最大独立集.最大独立集=n-最大匹配. #include&l ...
- P3355 骑士共存问题 (最小割)
题意:nxn的棋盘 有m个坏点 求能在棋盘上放多少个马不会互相攻击 题解:这个题仔细想想居然和方格取数是一样的!!! 每个马他能攻击到的地方的坐标 (x+y)奇偶性不一样 于是就黑白染色 s-> ...
随机推荐
- 普冉PY32系列(十五) PY32F0系列的低功耗模式
目录 普冉PY32系列(一) PY32F0系列32位Cortex M0+ MCU简介 普冉PY32系列(二) Ubuntu GCC Toolchain和VSCode开发环境 普冉PY32系列(三) P ...
- 一文搞懂 ARM 64 系列: ADC
1 指令语法 adc <Xd>, <Xn>, <Xm> 2 指令语义 adc就是带「进位」加法,指令中的c就是英文carry. 整个指令等价于: (Xd, _) = ...
- HEOI 2024游记
(虽然是体验罢 HEOI2024游记 前 \(\,\,\)省选! \(\,\,\)得知省选可以报名体验的时候着实很兴奋 也是不假思索的就报了 Day 0 本来说是九点上大巴 结果硬生拖到十点半(恼 分 ...
- 八大远程控制软件,完美替代Teamviewer
理想情况下,最好的远程桌面软件应该物有所值,同时为用户提供快速.安全和可靠的远程连接.还应该有一套强大的解决方案,提供高级报告和增强功能.跨平台支持和通信. TeamViewer 拥有超过 25 亿的 ...
- 当字符遇上 scanf() 要当心
当字符遇上 scanf() 要当心 看一下程序 char ch1,ch2; printf("请输入ch1,ch2的值:"); scanf("%c %c",&am ...
- 智能工作流:Spring AI高效批量化提示访问方案
基于SpringAI搭建系统,依靠线程池\负载均衡等技术进行请求优化,用于解决科研&开发过程中对GPT接口进行批量化接口请求中出现的问题. github地址:https://github.co ...
- 字节面试:说说Java中的锁机制?
Java 中的锁(Locking)机制主要是为了解决多线程环境下,对共享资源并发访问时的同步和互斥控制,以确保共享资源的安全访问. 锁的作用主要体现在以下几个方面: 互斥访问:确保在任何时刻,只有一个 ...
- C 语言编程 — GDB 调试工具
目录 文章目录 目录 前文列表 代码调试 GDB 启动 GDB 交互命令 运行程序 暂停程序 设置断点 设置观察点 设置捕捉点 打印信息 查询运行信息 分割窗口 前文列表 <程序编译流程与 GC ...
- 大数据之Hadoop的HDFS存储优化—异构存储(冷热数据分离)
异构存储主要解决,不同的数据,储存在不同类型的硬盘中,达到最佳性能的问题 1)存储类型 RAM_DISK:内存镜像文件系统 SSD:SSD固态硬盘 DISK:普通磁盘,在HDFS中,如果没有主动声明数 ...
- mews/captcha 验证码组件
/** * 图像验证码 */ public function captcha(CaptchaBridge $captcha, $type = 'default') { $api_captcha = $ ...