题目链接: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 骑士共存问题题解的更多相关文章

  1. P3355 骑士共存问题

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

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

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

  3. 网络流棋盘模型 | P3355 骑士共存问题 P4304 [TJOI2013]攻击装置

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

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

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

  5. 洛谷P3355 骑士共存问题

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

  6. P3355 骑士共存问题【洛谷】(二分图最大独立集变形题) //链接矩阵存图

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

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

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

  8. 【Luogu】P3355骑士共存问题(最小割)

    题目链接 像题面那样把棋盘染成红黄点.发现骑士迈一步能到达的点的颜色一定是跟他所在的格子的颜色不同的.于是(woc哪来的于是?这个性质有这么明显吗?)从源点向所有红点连边,从所有黄点向汇点连边,红点向 ...

  9. LUOGU P3355 骑士共存问题(二分图最大独立集)

    传送门 因为骑士只能走"日"字,所以一定是从一个奇点到偶点或偶点到奇点,那么这就是一张二分图,题目要求的其实就是二分图的最大独立集.最大独立集=n-最大匹配. #include&l ...

  10. P3355 骑士共存问题 (最小割)

    题意:nxn的棋盘 有m个坏点 求能在棋盘上放多少个马不会互相攻击 题解:这个题仔细想想居然和方格取数是一样的!!! 每个马他能攻击到的地方的坐标 (x+y)奇偶性不一样 于是就黑白染色 s-> ...

随机推荐

  1. WEB服务与NGINX(26)- 实现Nginx高并发系统内核参数优化

    1. 实现Nginx高并发系统内核参数优化 由于默认的Linux内核参数考虑的是最通用场景,这明显不符合用于支持高并发访问的Web服务器的定义,所以需要修改Linux内核参数,使得Nginx可以拥有更 ...

  2. CompletableFuture学习总结

    CompletableFuture 简介 在Java8中,CompletableFuture提供了非常强大的Future的扩展功能,可以帮助我们简化异步编程的复杂性,并且提供了函数式编程的能力,可以通 ...

  3. grid布局方案

    前言 CSS网格布局用于将页面分割成数个主要区域,或者用来定义组件内部元素间大小.位置和图层之间的关系.像表格一样,网格布局让我们能够按行或列来对齐元素. 但是,使用CSS网格可能还是比CSS表格更容 ...

  4. Vue3 项目

    创建 Vue3 项目的步骤如下: 安装 Node.js Vue3 需要依赖 Node.js 环境,因此需要先安装 Node.js.可以从官网下载 Node.js 的安装包并安装,也可以使用包管理器安装 ...

  5. 阿克曼函数(Ackermann function)部分推导

    相关题目 已知\(Ackermann function\)为 \[Ack(m,n)=\begin{cases}n+1(m=0) \\ Ack(m-1,1)(m>0,n=0) \\ Ack(m-1 ...

  6. 4G EPS 的架构模型

    目录 文章目录 目录 前文列表 EPS 的架构 EPS 的架构模型 E-UTRAN UE eNodeB EPC MME(移动性管理) SGW(本地移动性锚点) PGW(业务锚点) HSS(用户认证及鉴 ...

  7. Angular快速生成文件基本命令

    ng new 作用:创建一个已被初始化的Angular应用 命令选项 参数 说明 --collection -c 指定工程模板 属于高阶操作,暂不知道如何使用 --directory 指定新项目创建的 ...

  8. 用pageOffice控件实现 office word文档 强制留痕编辑Word

    OA办公中,业务需要多人编辑word文档,需要强制留痕功能,用来查看文档编辑过程中的具体修改痕迹. 怎么实现word文档的强制留痕呢? 1 实现方法 通过pageOffice实现简单的在线打开编辑wo ...

  9. GeminiDB PITR,让游戏回档“进退自如”!

    本文分享自华为云社区<GeminiDB PITR,让游戏回档"进退自如"!>,作者:GaussDB 数据库. 在实际业务场景中,客户数据库难免会出现数据损毁.数据丢失. ...

  10. 发现了一个膨胀样式的css库

    众所周知,对于前端来说css是最难的了,如果你遇到了一个脑洞大奇思妙想的产品,那就更难了. 很不巧,了不起就经受过这样的痛苦,产品经理看了HarmonyOS4的发布会,脑子一热就让设计师出了一套膨胀蓬 ...