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-> ...
随机推荐
- LMDeploy量化部署LLM&LVM实操-书生浦语大模型实战营第二期第5节作业
书生浦语大模型实战营第二期第5节作业 本页面包括实战营第二期第五节作业的全部操作步骤.如果需要知道模型量化部署的相关知识请访问学习笔记. 作业要求 基础作业 完成以下任务,并将实现过程记录截图: 配置 ...
- JSON字符串数据转换指定实体对象数据
一.引入需要的maven依赖 <dependency> <groupId>org.projectlombok</groupId> <artifactId> ...
- PHP实现没有数据库提交form表单到后台并且显示出数据列表(Vuejs和Element-UI前端设计表单)
1.情境:如果你新建了个网站,却没有数据库服务器,如何把你的表单信息,提交到服务端后台,收集数据. 2.思路:如果用传统的form action 提交到一个form.php页面,此时只能存储一次数据, ...
- 使用DP-Modeler、ModelFun模方软件修复实景三维模型教程
P-Modeler DP-Modeler是武汉天际航自主研发的一款集精细化单体建模与Mesh网格模型修饰于一体的软件.支持三维模型一键水面修复.道路置平.建筑局部修饰.删除底部碎片.植被处理.桥隧 ...
- HDU-Employment Planning题解
题目在这里 -------------------------------- Employment Planning 简单的一道dp 关键的点在于想到用枚举实现各种情况的讨论 关键的注释写在代码里了 ...
- 远程控制软件 TeamViewer 的局限性和替代方案
TeamViewer 公司创建于2005年,总部位于德国,客户遍及全球,其中企业用户居多,其各方面性能都很不错,但价格却非常贵.针对个人用户,TeamViewer 提供免费版软件,但时不时会提示&qu ...
- Chrome:用uBlacklist屏蔽CSDN搜索结果
CSDN现在广告满天飞,且很多博客需要先关注才能复制,非常令人无语.如果每次用Google搜索的时候都要加上"-csdn"选项,就非常麻烦.有没有更方便的办法呢?我们可以利用Chr ...
- Oracle批量插入和更新
一.驱动.使用Oracle.ManagedDataAccess.Client 二.原理.利用OracleCommand的ArrayBindCount属性设置批量大小. 三.实现 函数使用的实体是efc ...
- 珠排序算法C# 简单实现 奇葩排序中的算盘排序(算珠排序)算法
Console.WriteLine("Hello World!"); int[] arr = { 1, 3, 4, 0, 22, 4,0, 6, 3,10,8,6,7 }; Con ...
- RocketMQ消息过滤机制源码详解
#RocketMQ提供了2种消息过滤的方式: TAG 过滤 SQL92 过滤 SQL过滤默认是没有打开的,如果想要支持,必须在broker的配置文件中设置:enablePropertyFilter = ...