BZOJ4651 & 洛谷1173 & UOJ220:[NOI2016]网格——题解(附debug数据)
https://www.lydsy.com/JudgeOnline/problem.php?id=4651
https://www.luogu.org/problemnew/show/P1173#sub
跳蚤国王和蛐蛐国王在玩一个游戏。他们在一个 n 行 m 列的网格上排兵布阵。其中的 c 个格子中 (0≤c≤nm),每个格子有一只蛐蛐,其余的格子中,每个格子有一只跳蚤。我们称占据的格子有公共边的两只跳蚤是相邻的。我们称两只跳蚤是连通的,当且仅当这两只跳蚤相邻,或存在另一只跳蚤与这两只跳蚤都连通。现在,蛐蛐国王希望,将某些(0 个,1 个或多个)跳蚤替换成蛐蛐,使得在此之后存在至少两只跳蚤不连通。例如:我们用图表示一只跳蚤,用图表示一只蛐蛐,那么图 1 描述了一个 n=4,m=4,c=2的情况。这种情况下蛐蛐国王可以通过将第 2 行第 2 列,和第 3 行第 3 列的两只跳蚤替换为蛐蛐,从而达成他的希望,如图 2 所示。并且,不存在更优的方案,但是可能存在其他替换 2 只跳蚤的方案。你需要首先判断蛐蛐国王的希望能否被达成。如果能够达成,你还需要最小化被替换的跳蚤的个数。
这题是一道十分变态的码农分类讨论题。
参考:https://www.cnblogs.com/ljh2000-jump/p/6373541.html
显然答案就四种:"-1,0,1,2"。
-1就是只有一个跳蚤或者只有两个相邻的跳蚤。
0就是蛐蛐已经把跳蚤分开了。
1情况思考,我们把相邻的跳蚤连边,如果有割点的话,我们只要在割点处放一个蛐蛐就行了。
剩下的情况就是2了。
然而跳蚤的个数有点多,我们只能拿几个跳蚤出来建图跑tarjan。
一个优秀的方法是拿已放好的蛐蛐为中心5*5的方格内的跳蚤。
(PS:为什么不拿3*3的呢?因为如果蛐蛐在边界上的话有割点那也是假的,为了防止假割点于是在外围再放一层,思考一下。)
查找蛐蛐和跳蚤的坐标用map会奇慢(血的教训*1),所以写哈希表存。
另外,外面一层的跳蚤如果产生割点,同理也是假的,不予理会即可。
然后就是uoj的hack数据了,这里提供些debug数据,仅供参考。
ans: -
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<cstdio>
#include<cctype>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef double dl;
const int INF=2e9;
const int N=1e5+;
const int M=N*;
const int P=;
const int B=1e9+;
inline int read(){
int X=,w=;char ch=;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
struct Hash{
int cnt,head[P],nxt[M];
ll to[M];
inline void init(){
cnt=;memset(head,,sizeof(head));
}
inline void add(ll x,ll y){
ll v=(x*B+y);int u=v%P;
to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;
}
inline int qry(ll x,ll y){
ll v=(x*B+y);int u=v%P;
for(int i=head[u];i;i=nxt[i])
if(to[i]==v)return i;
return ;
}
}mp1,mp2;
struct node{
int x,y;
}p[N],q[M];
int im[M],n,m,c;
int DX[]={,,-,};
int DY[]={,,,-};
int dx[]={-,-,-,-,-,-,-,-,-,-,,,,,,,,,,,,,,};
int dy[]={-,-,,,,-,-,,,,-,-,,,-,-,,,,-,-,,,};
inline dl dis(dl x1,dl y1,dl x2,dl y2){
dl x=x1-x2,y=y1-y2;
return sqrt(x*x+y*y);
}
struct edge{
int to,nxt;
}e[M*];
int cnt,head[M],dfn[M],low[M],to[M],id,t,rtson;
bool cut[M];
inline void add(int u,int v){
e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt;
}
void tarjan(int u,int f){
to[u]=id;dfn[u]=low[u]=++t;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(!dfn[v]){
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u]&&f)cut[u]=;
if(!f)rtson++;
}else if(f!=v)
low[u]=min(low[u],dfn[v]);
}
if(!f&&rtson>=)cut[u]=;
}
bool vis1[M],vis2[M];
int dui[M],top;
inline void init(){
for(int i=;i<=mp1.cnt;i++)vis2[i]=;
for(int i=;i<=mp2.cnt;i++)cut[i]=head[i]=low[i]=dfn[i]=to[i]=vis1[i]=;
mp1.init();mp2.init();t=cnt=;
}
inline void getnode(int x,int y,int iid){
vis2[iid]=;
for(int i=;i<;i++){
int nx=x+DX[i],ny=y+DY[i];
if(nx<||nx>n||ny<||ny>m)continue;
int nxtid=mp1.qry(nx,ny);
if(nxtid)continue;
int tmp=mp2.qry(nx,ny);
if(vis1[tmp])continue;
vis1[tmp]=;dui[++top]=tmp;
}
for(int i=;i<;i++){
int nx=x+DX[i],ny=y+DY[i];
if(nx<||nx>n||ny<||ny>m)continue;
int nxtid=mp1.qry(nx,ny);
if(nxtid){
if(!vis2[nxtid])getnode(nx,ny,nxtid);
continue;
}
}
for(int i=;i<;i++){
int nx=x+DX[i],ny=y+DY[i];
if(nx<||nx>n||ny<||ny>m)continue;
vis1[mp2.qry(nx,ny)]=;
}
}
inline void solve(){
for(int i=;i<=mp2.cnt;i++)
if(!dfn[i]){
id++;rtson=;tarjan(i,);
}
for(int i=;i<=c;i++){
if(vis2[i])continue;
top=;getnode(p[i].x,p[i].y,i);
for(int j=;j<=top;j++)
if(to[dui[j]]!=to[dui[]]){puts("");return;}
}
if(n==||m==){puts("");return;}
for(int i=;i<=mp2.cnt;i++)
if(cut[i]&&im[i]==){
puts("");return;
}
puts("");
}
inline bool find(){
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
if(!mp1.qry(i,j)){
for(int k=;k<;k++){
int x=i+DX[k],y=j+DY[k];
if(x<||x>n||y<||y>m)continue;
if(!mp1.qry(x,y))return ;
}
return ;
}
}
}
return ;
}
int main(){
int T=read();
while(T--){
init();
n=read(),m=read(),c=read();
for(int i=;i<=c;i++){
p[i].x=read(),p[i].y=read();
mp1.add(p[i].x,p[i].y);
}
if((ll)n*m-c<=||((ll)n*m-c==&&find())){puts("-1");continue;}
for(int i=;i<=c;i++){
int x=p[i].x,y=p[i].y;
for(int j=;j<;j++){
int nx=x+dx[j],ny=y+dy[j];
if(nx<||nx>n||ny<||ny>m||mp1.qry(nx,ny))continue;
int tmp=mp2.qry(nx,ny);
if(!tmp){
mp2.add(nx,ny);
if(dis(x,y,nx,ny)<1.9)im[mp2.cnt]=;
else im[mp2.cnt]=;
q[mp2.cnt]=(node){nx,ny};
}else{
if(dis(x,y,nx,ny)<1.9)im[tmp]=;
else im[tmp]=min(,im[tmp]);
}
}
}
for(int i=;i<=mp2.cnt;i++){
int x=q[i].x,y=q[i].y;
for(int j=;j<;j++){
int nx=x+DX[j],ny=y+DY[j];
if(nx<||nx>n||ny<||ny>m)continue;
int tmp=mp2.qry(nx,ny);
if(tmp&&im[tmp])add(i,tmp);
}
}
solve();
}
return ;
}
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++
BZOJ4651 & 洛谷1173 & UOJ220:[NOI2016]网格——题解(附debug数据)的更多相关文章
- 洛谷P1783 海滩防御 分析+题解代码
洛谷P1783 海滩防御 分析+题解代码 题目描述: WLP同学最近迷上了一款网络联机对战游戏(终于知道为毛JOHNKRAM每天刷洛谷效率那么低了),但是他却为了这个游戏很苦恼,因为他在海边的造船厂和 ...
- 洛谷P4047 [JSOI2010]部落划分题解
洛谷P4047 [JSOI2010]部落划分题解 题目描述 聪聪研究发现,荒岛野人总是过着群居的生活,但是,并不是整个荒岛上的所有野人都属于同一个部落,野人们总是拉帮结派形成属于自己的部落,不同的部落 ...
- 洛谷P1155 双栈排序题解(图论模型转换+二分图染色+栈)
洛谷P1155 双栈排序题解(图论模型转换+二分图染色+栈) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1311990 原题地址:洛谷P1155 双栈排序 ...
- 洛谷10月月赛II题解
[咻咻咻] (https://www.luogu.org/contestnew/show/11616) 令人窒息的洛谷月赛,即将参加NOIp的我竟然只会一道题(也可以说一道也不会),最终145的我只能 ...
- [洛谷P1823]音乐会的等待 题解(单调栈)
[洛谷P1823]音乐会的等待 Description N个人正在排队进入一个音乐会.人们等得很无聊,于是他们开始转来转去,想在队伍里寻找自己的熟人.队列中任意两个人A和B,如果他们是相邻或他们之间没 ...
- BZOJ2527 & 洛谷3527:[Poi2011]Meteors——题解
+++++++++++++++++++++++++++++++++++++++++++ +本文作者:luyouqi233. + +欢迎访问我的博客:http://www.cnblogs.com/luy ...
- 洛谷 p1516 青蛙的约会 题解
dalao们真是太强了,吊打我无名蒟蒻 我连题解都看不懂,在此篇题解中,我尽量用语言描述,不用公式推导(dalao喜欢看公式的话绕道,这篇题解留给像我一样弱的) 进入正题 如果不会扩展欧里几德的话请先 ...
- 洛谷p2370yyy2015c01的U盘题解
没什么特殊的想法 就是看自己很久没有更新关于题解类的文章了而已 (其实这是我好久之前做的, 只是把它从洛谷博客搬到了这里而已) 题目 首先分析题目要二分 他长成这个亚子太二分了 所以就要二分 最好是先 ...
- 2019.06.17课件:[洛谷P1310]表达式的值 题解
P1310 表达式的值 题目描述 给你一个带括号的布尔表达式,其中+表示或操作|,*表示与操作&,先算*再算+.但是待操作的数字(布尔值)不输入. 求能使最终整个式子的值为0的方案数. 题外话 ...
随机推荐
- 一个小白的测试环境docker化之路
本文来自网易云社区 作者:叶子 学习docker搭建测试环境断断续续也有三个多月了,希望记录一下这个过程.常言道,总结过去,展望未来嘛~文章浅显,还望各位大神路过轻拍. 按照国际惯例,先说一下背景: ...
- libevent学习八(evbuffer)
1.evbuffer以队列的形式管理字节,从尾部添加,从头部取出(FIFO) 2.evbuffer内部存储形式是多个独立的连续内存 接口 //创建和删除 struct evbuffer * ...
- hdu2899Strange fuction(解方程+二分)
Strange fuction Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- hdu1061Rightmost Digit(快速幂取余)
Rightmost Digit Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)T ...
- 【转】Unity 使用xLua遇到的坑
在我们使用xLua作为Unity中lua集成的解决方案时,遇到了一个问题,就是当我们使用在lua中把UI中的某个控件绑定相应的事件(如按钮的onClick事件),xLua绑定这个事件是用委托实现的,具 ...
- Python数据分析基础——Numpy tutorial
参考link https://docs.scipy.org/doc/numpy-dev/user/quickstart.html 基础 Numpy主要用于处理多维数组,数组中元素通常是数字,索引值为 ...
- 同台服务器 部署多个tomcat 需要做的修改
需要修改以下加粗部分: 1:访问端口 8080->8081 2:shutdown 端口 8005->8015 3: AJP端口 8001->8010 <?xml version ...
- docker学习2
今天继续学习docker! 搜索镜像 docker search centos 下载镜像 docker pull name(镜像名字) 查看镜像docker images 字段含义分析: TAG:仓库 ...
- 孵化器使用Office365的场景及收益
- 线性代数之——微分方程和 exp(At)
本节的核心是将常系数微分方程转化为线性代数问题. \[\frac{du}{dt}=\lambda u \quad 的解为 \quad u(t) = Ce^{\lambda t}\] 代入 \(t=0\ ...