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-> ...
随机推荐
- [Python急救站]基于Transformer Models模型完成GPT2的学生AIGC学习训练模型
为了AIGC的学习,我做了一个基于Transformer Models模型完成GPT2的学生AIGC学习训练模型,指在训练模型中学习编程AI. 在编程之前需要准备一些文件: 首先,先win+R打开运行 ...
- ES_CCS/R(二):跨集群搜索 Cross-cluster search (CCS)
跨集群搜索(cross-cluster search)使你可以针对一个或多个远程集群运行单个搜索请求. 例如,你可以使用跨集群搜索来筛选和分析存储在不同数据中心的集群中的日志数据. 示例 :在一个集群 ...
- 简说Python之ipython的pdb调试
目录 简说Python之ipython 1.安装ipython 2.ipython的使用 3.ipython的debug调试. 系统环境:Ubuntu 18.04.1 LTS Python使用的是虚拟 ...
- juc之ConcurrentHashMap在我工作中的实践
Map是我工作中应用比较多的数据结构之一,主要用来存储一些kv的映射信息,如果是单线程环境下我会优先使用HashMap,但是如果在多线程环境下继续使用HashMap我不确定会不会被我老大打死,为了生命 ...
- docker-compose搭建的Mysql主主复制
注意下面几点: 1)要保证同步服务期间之间的网络联通.即能相互`ping`通,能使用对方授权信息连接到对方数据库(防火墙开放3306端口). 2)关闭selinux. 3)同步前,双方数据库中需要同步 ...
- SpringBoot-Http请求工具类
一.编写请求配置类 import com.alibaba.fastjson.JSONObject; import org.springframework.context.annotation.Conf ...
- 数据转换2-无人机航拍倾斜摄影转换成OSGB格式
首先软件的下载和安装参考下面链接 http://www.xue51.com/soft/53013.html 0.首先打开软件,要打开2个哦. 打数据处理开后台 ContextCapture Engin ...
- 从零开始写 Docker(十四)---重构:实现容器间 rootfs 隔离
本文为从零开始写 Docker 系列第十四篇,实现容器间的 rootfs 隔离,使得多个容器间互不影响. 完整代码见:https://github.com/lixd/mydocker 欢迎 Star ...
- gcc版本升级
升级链接: CentOS 7 gcc版本需升级到7.5.0 ,详细可参考文档:https://learn.microsoft.com/zh-cn/azure/cognitive-services/sp ...
- Instsrv.exe 与 Srvany.exe 安装Windows服务
原理:Instsrv.exe可以给系统安装和删除服务 Srvany.exe可以让exe程序以服务的方式运行(Srvany只是exe注册程序的服务外壳,可以通过它让我们的程序以SYSTEM账户活动,随电 ...