P1173 [NOI2016] 网格

题目提供者洛谷

难度NOI/NOI+/CTSC

历史分数100

题目描述

跳蚤国王和蛐蛐国王在玩一个游戏。

他们在一个 n 行 m 列的网格上排兵布阵。其中的 cc 个格子中 (0 ≤ c ≤ n⋅m),每个格子有一只蛐蛐,其余的格子中,每个格子有一只跳蚤。

我们称占据的格子有公共边的两只跳蚤是相邻的。

我们称两只跳蚤是连通的,当且仅当这两只跳蚤相邻,或存在另一只跳蚤与这两只跳蚤都连通。

现在,蛐蛐国王希望,将某些(零个,一个或多个)跳蚤替换成蛐蛐,使得在此之后存在至少两只跳蚤不连通。[图片]

例如:图 1 描述了一个 n=4,m=4,c=2 的情况。

这种情况下蛐蛐国王可以通过将第二行第二列,和第三行第三列的两只跳蚤替换为蛐蛐,从而达成他的希望,如右图所示。并且,不存在更优的方案,但是可能存在其他替换两只跳蚤的方案。

你需要首先判断蛐蛐国王的希望能否被达成。如果能够达成,你还需要最小化被替换的跳蚤的个数。

输入格式

每个输入文件包含多组数据。

输入文件的第一行只有一个整数 T,表示数据的组数。

接下来依次输入 TT 组数据,每组数据的第一行包含三个整数 n,m,c。

接下来 c 行,每行包含两个整数 x,y 表示第 x 行,第 y 列的格子被一个蛐蛐占据。每一组数据当中,同一个蛐蛐不会被多次描述。

输出格式

对于每一组数据依次输出一行答案。

如果这组数据中,蛐蛐国王的希望不能被达成,输出 -1。否则,输出被替换的跳蚤的个数的最小值。

输入输出样例

输入 #1

4
4 4 2
1 1
4 4
2 3 1
1 2
2 2 2
1 1
2 2
1 1 0

输出 #1

2
1
0
-1

 

说明/提示

样例解释

第一组数据就是问题描述中的例子。

对于第二组数据,可以将第二行第二列的一只跳蚤替换为蛐蛐,从而使得存在两只跳蚤不连通,并且不存在更优的方案。

对于第三组数据,最初已经存在两只跳蚤不连通,故不需要再进行替换。

对于第四组数据,由于最多只有一只跳蚤,所以无论如何替换都不能存在两只跳蚤不连通。

数据范围

对于全部的测试点,保证1≤T≤20。我们记 ∑c 为某个测试点中,其 T 组输入数据的所有 c 的总和。对于所有的测试点,∑c≤105。

对于全部的数据,满足 1≤n,m≤10^9,0≤c≤n×m,1≤x≤n,1≤y≤m。

每个测试点的详细数据范围见下表。表中的 n,m,c 均是对于单个输入数据(而非测试点)而言的,也就是说同一个测试点下的 T 组数据均满足限制条件;而 ∑c是对于单个测试点而言的。为了方便阅读,“测试点”一列被放到了表格的中间而不是左边。

 解题思路:

 将有蛐蛐的看做黑点,有跳蚤的看做白点。

显然答案只可以是无解或者 0,1,2。

  • 若所有四联通的白色格子组成的图不连通,则答案是 0。

  • 否则若图有割点,则答案为 1

  • 否则若图只有不超过两个点,则无解

  • 否则为 2

前三个情况是显然的,最后一种情况可以分图有 33 个点和超过 33 个分别证明。

于是直接建图跑 tarjan 即可 O(nm)。

然而这张图点很多但是空位很少,考虑将其缩成一个点数边数均为O(c) 的图使得缩完答案不变。

考虑只保留以下白点:

  • 与网格四个角的至少一个角的 x,yx,y 坐标之差 \leq2≤2

  • 与某个黑点八连通

  • 在网格的上边或下边上,且所在列有至少一个黑点

  • 在网格的左边或右边上,且所在行有至少一个黑点

然后对于所有剩下的白点,若两个白点点在同一行或者同一列,且中间没有其它点(包括黑点黑剩下的白点),就连一条边。

注意并不是只建四连通的边。

例如这样,蓝色的格子是保留下来的点。

然后发现这张图的答案与原图的答案大多数情况是一样的,但判 -1 的时候需要特判一下若图有两个点但这两个点虽然有边但不四连通的情况,这种情况实际上会有至少三个点在里面,答案是 1,或者可以判一下n=1,m=1 也可以。

我也不知道是不是对的,以及如果是对的咋证,反正过了所有 uoj hack 数据,欢迎继续hack。

而且考虑每个黑点只会最多贡献它周围 8 个,以及边上 4 个共 12 个点,所以一共O(c) 个点。

所以复杂度瓶颈在于建图,复杂度Θ(clogc)

标准代码:

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
typedef long long ll;
const int dx[4]={0,1,0,-1};
const int dy[4]={1,0,-1,0};
const int P=1000117;
const int N=100050;
char rB[1<<21],*rS,*rT;
inline char gc(){return rS==rT&&(rT=(rS=rB)+fread(rB,1,1<<21,stdin),rS==rT)?EOF:*rS++;}
inline int rd(){
    char c=gc();
    while(c<48||c>57)c=gc();
    int x=c&15;
    for(c=gc();c>=48&&c<=57;c=gc())x=(x<<3)+(x<<1)+(c&15);
    return x;
}
int x[N],y[N],G[N*24],to[N*192],nxt[N*192],sz,cnt,pre[N*24],dfsc,n,m,c,tmpx[N*24],tmpy[N*24],ctmp;
bool isok[N*24],iscut[N*24];
struct node{
	int x,y;
	node(){}
	node(int x,int y):x(x),y(y){}
};
queue<node> Q,q;
struct Hash{  //用hash实现map
	int h[P],vx[N*25],vy[N*25],p[N*25],nxt[N*25],sz;
	inline void clear(){
		memset(h,0,sizeof(h));sz=0;
	}
	inline void ins(int x,int y,int id){
		int pos=((ll)(x-1)*n+y-1)%P;
		vx[++sz]=x;vy[sz]=y;p[sz]=id;nxt[sz]=h[pos];h[pos]=sz;
	}
	inline int ask(int x,int y){
		for(int k=h[((ll)(x-1)*n+y-1)%P];k;k=nxt[k])if(vx[k]==x&&vy[k]==y)return p[k];
		return 0;
	}
}h,col,tem;
inline int Abs(int x){return x<0?-x:x;}
inline int Max(int a,int b){return a>b?a:b;}
inline void add(int u,int v){
	to[++sz]=v;nxt[sz]=G[u];G[u]=sz;
	to[++sz]=u;nxt[sz]=G[v];G[v]=sz;
}
inline bool check(){
	int i,j,k,tx,ty;
	for(i=1;i<=n;++i)
		for(j=1;j<=m;++j)if(!h.ask(i,j)){
			for(k=0;k<4;++k)if((tx=i+dx[k])&&tx<=n&&(ty=j+dy[k])&&ty<=m&&!h.ask(tx,ty))return 1;
			return 0;
		}
}
inline void bfs(int sx,int sy,int cl){  //第一次floodfill
	int i,u,v,tx,ty;
	q.push(node(sx,sy));col.ins(sx,sy,cl);
	while(!q.empty()){
		u=q.front().x;v=q.front().y;q.pop();
		for(i=0;i<4;++i)if((tx=u+dx[i])&&tx<=n&&(ty=v+dy[i])&&ty<=m&&h.ask(tx,ty)>0&&!col.ask(tx,ty)){
			col.ins(tx,ty,cl);  //用col来记录所属联通块编号(也成为颜色)
			q.push(node(tx,ty));
		}
	}
}
inline bool bfs2(int sx,int sy){
	int i,u,v,x,y,t;
	q.push(node(sx,sy));tem.ins(sx,sy,-1);
	while(!q.empty()){
		u=q.front().x;v=q.front().y;q.pop();
		for(x=Max(1,u-1);x<=n&&x<=u+1;++x)
			for(y=Max(1,v-1);y<=m&&y<=v+1;++y)if((t=h.ask(x,y))&&!tem.ask(x,y))if(t==-1){
				tem.ins(x,y,-1);  //用tem来防止对障碍结点重复访问
//对跳蚤结点的重复访问最多总共c*8个,不会影响复杂度
				q.push(node(x,y));
			}else{tmpx[++ctmp]=x;tmpy[ctmp]=y;}
	}
	if(ctmp==-1)return 1;
	for(i=1,t=col.ask(tmpx[0],tmpy[0]);i<=ctmp;++i)if(col.ask(tmpx[i],tmpy[i])!=t)return 0;
	return 1;
}
inline bool ncon(){  //判断是否不连通
	int i,u,v,ccl=0;
	col.clear();
	while(!Q.empty()){
		u=Q.front().x;v=Q.front().y;Q.pop();
		if(col.ask(u,v))continue;
		bfs(u,v,++ccl);
	}
	tem.clear();
	for(i=0;i<c;++i)if(!tem.ask(x[i],y[i])){
		ctmp=-1;
		if(!bfs2(x[i],y[i]))return 1;
	}
	return 0;
}
int dfs(int u,int fa){  //dfs求割顶
	int i,v,lowu=pre[u]=++dfsc,lowv,chd=0;
	for(i=G[u];i;i=nxt[i])if((v=to[i])!=fa)if(!pre[v]){
		++chd;
		if((lowv=dfs(v,u))>=pre[u])iscut[u]=1;
		if(lowv<lowu)lowu=lowv;
	}else if(pre[v]<lowu)lowu=pre[v];
	if(!fa&&chd==1)iscut[u]=0;
	return lowu;
}
int main(){
	int T=rd(),i,j,k,l,t,tt,tx,ty;
	bool ok;
	while(T--){
		n=rd();m=rd();c=rd();
		h.clear();
		for(i=0;i<c;++i){
			x[i]=rd();y[i]=rd();
			h.ins(x[i],y[i],-1);
		}
		if((ll)n*m-c<2ll){
			puts("-1");
			continue;
		}
		if((ll)n*m-c==2ll){
			puts(check()?"-1":"0");
			continue;
		}
		memset(G,0,sizeof(G));ok=sz=cnt=dfsc=0;
		memset(pre,0,sizeof(pre));
		memset(iscut,0,sizeof(iscut));
		memset(isok,0,sizeof(isok));
        //建图
		for(i=0;i<c;++i)
			for(j=Max(1,x[i]-2);j<=x[i]+2&&j<=n;++j)
				for(k=Max(1,y[i]-2);k<=y[i]+2&&k<=m;++k)if(!(t=h.ask(j,k))){
					h.ins(j,k,++cnt);Q.push(node(j,k));
					isok[cnt]=Max(Abs(j-x[i]),Abs(k-y[i]))<=1;
					for(l=0;l<4;++l)if((tx=j+dx[l])&&tx<=n&&(ty=k+dy[l])&&ty<=m&&(tt=h.ask(tx,ty))>0)add(cnt,tt);
				}else if(t>0&&Max(Abs(j-x[i]),Abs(k-y[i]))<=1)isok[t]=1;
		if(ncon()){
			puts("0");
			continue;
		}
		if(n==1||m==1){  //一行或一列可以特判
			puts("1");
			continue;
		}
		for(i=1;i<=cnt;++i){
			if(!pre[i])dfs(i,0);
			if(isok[i]&&iscut[i]){
				puts("1");
				ok=1;break;
			}
		}
		if(!ok)puts("2");
	}
	return 0;
}

通过图片:

谢谢观看! 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/60066.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

安卓证书生成教程

1.下载安装JDK文件&#xff08;如已安装请跳过&#xff09; 根据电脑系统版本下载JDK版本文件 下载地址&#xff1a;[https://www.oracle.com/java/technologies/downloads/](https://www.oracle.com/java/technologies/downloads/) 如果电脑上安装过JDK文件可以跳过2.生成密钥…

解决mvn clean install遇到testng单元测试失败时打包也失败的问题

解决mvn clean install遇到testng单元测试失败时打包也失败的问题 看这个之前请先看这个 Jenkins执行Testng 比如我现在就有一个单元测试失败的项目 执行mvn clean install的时候就会报错 下面是我现在的pom.xml 但我们不希望这样&#xff0c;怎么办 <plugin><gr…

【JVM】(一)深入理解JVM运行时数据区

文章目录 一、JVM 运行流程二、虚拟机栈&#xff08;线程私有&#xff09;三、本地方法栈 &#xff08;线程私有&#xff09;四、方法区&#xff08;元数据区&#xff09;五、堆&#xff08;线程共享&#xff09;六、程序计数器&#xff08;线程私有&#xff09; 一、JVM 运行流…

【C++】开源:sqlite3数据库配置使用

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍sqlite3数据库配置使用。 无专精则不能成&#xff0c;无涉猎则不能通。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c;下…

winform学习(3)-----Windows窗体应用和Windows窗体应用(.Net Framework)有啥区别?

1.模板选择 在学习winform的时候总是会对这两个应用不知道选择哪个&#xff1f;而且在学习的时候也没有具体的说明 首先说一下我是在添加控件的时候出现了以下问题 对于使用了Windows窗体应用这个模板的文件在工具箱中死活不见控件。 在转换使用了Windows窗体应用(.NET Fram…

性价比最高的护眼台灯是哪一款?性价比高的护眼台灯盘点

现在的孩子&#xff0c;不是以往的孩子那么的无忧无虑&#xff0c;他们要考虑的是学习的成绩&#xff0c;所以很多孩子为了能在父母面前能得到夸奖&#xff0c;就努力的学习&#xff0c;那么台灯就不可缺少&#xff0c;但是如今市场上的台灯太多了&#xff0c;如果你购买的台灯…

element表格+表单+表单验证结合u

一、结果展示 1、图片 2、描述 table中放form表单&#xff0c;放输入框或下拉框或多选框等&#xff1b; 点击添加按钮&#xff0c;首先验证表单&#xff0c;如果存在没填的就验证提醒&#xff0c;都填了就向下添加一行表单表格&#xff1b; 点击当前行删除按钮&#xff0c;…

linux鲁班猫屏幕和触摸[初用鲁班猫切换屏幕为MIPI-1080P][旋转屏幕为横屏显示][屏幕和触摸方向永久修改]

初用鲁班猫切换屏幕为MIPI-1080P 鲁班猫信息: 板卡从如下地址采购:https://detail.tmall.com/item.htm?_u110jcean66aa&id694560455663&spma1z09.2.0.0.56f52e8dj4eUdI&skuId5156903694777 鲁班猫官方文档和教程:https://doc.embedfire.com/linux/rk356x/quick_s…

【计算机视觉】BLIP:统一理解和生成的自举多模态模型

文章目录 一、导读二、背景和动机三、方法3.1 模型架构3.2 预训练目标3.3 BLIP 高效率利用噪声网络数据的方法&#xff1a;CapFilt 四、实验4.1 实验结果4.2 各个下游任务 BLIP 与其他 VLP 模型的对比 一、导读 BLIP 是一种多模态 Transformer 模型&#xff0c;主要针对以往的…

2023华数杯数学建模A题思路分析 - 隔热材料的结构优化控制研究

# 1 赛题 A 题 隔热材料的结构优化控制研究 新型隔热材料 A 具有优良的隔热特性&#xff0c;在航天、军工、石化、建筑、交通等 高科技领域中有着广泛的应用。 目前&#xff0c;由单根隔热材料 A 纤维编织成的织物&#xff0c;其热导率可以直接测出&#xff1b;但是 单根隔热…

【前端】鼠标事件计算与圆心形成的角度

在业务需求中&#xff0c;常常出现一些我们无法完成的效果图&#xff0c;这时需要UI切图给我们&#xff0c;而切图后不可避免的一些点击事件无法方便的监听 如该图圆环&#xff0c;其实是一张单独的图片&#xff0c;这种情况下只能通过js判断用户点击、拖动的鼠标位置&#xf…

【flink】开启savepoint

先启动一个任务 flink run -c com.yang.flink.CDCJob test-cdc.jar开启savepoint 命令&#xff1a; flink savepoint JobID 文件地址 flink savepoint e929a11d79bdc5e6f140f2cfb92e1335 file:///workspace/flinkSavepoints/backend这样就开启好了 操作中的错误 详细信…

xml的注释删要干净Parameter index out of range (2 > number of parameters, which is 1).

报了这个bugjava.sql.SQLException: Parameter index out of range (2 > number of parameters, which is 1). 对应sql语句是这样的 把注释删掉&#xff0c;就不报错了&#xff0c;这是什么奇葩bug

SolidWorks 3D Interconnect介绍

目前市面上有的三维设计软件有很多&#xff0c;如UG、Pro/E、CATIA等&#xff0c;而且每个三维设计软件都会生成自己文件格式。由于产品设计的原因&#xff0c;我们避免不了的会需要去使用不同三维设计软件的文件&#xff0c;这对于工程师来说其实是一件比较麻烦的事。 为什么…

简单上手FineBI

简介 安装下载 下载的是V6.0.11版本 设置管理员账号 账号admin 密码123456 新建分析主题 添加数据 选择本地数据上传 选择示例数据上传 打开效果如下&#xff0c;点击“确定”&#xff0c;这样就将示例数据上传到分析主题中 分析数据——编辑数据 如果数据质量好&#xf…

深入理解 Java Bean 的生命周期及各个阶段解析

目录 引言&#xff1a;一、什么是Java Bean二、Bean的生命周期概述三、Bean的创建阶段四、属性设置阶段初始化阶段六、使用阶段七、销毁阶段 引言&#xff1a; Java Bean是Java编程中经常使用的重要概念&#xff0c;它是可重用、可移植、可序列化的组件。在Java开发中&#xf…

数据可视化:Matplotlib详解及实战

1 Matplotlib介绍 Matplotlib是Python中最常用的可视化工具之一,可以非常方便地创建海量类型的2D图表和一些基本的3D图表。 Matplotlib提供了一个套面向绘图对象编程的API接口&#xff0c;能够很轻松地实现各种图像的绘制&#xff0c;并且它可以配合Python GUI工具&#xff08;…

k8s手动发布镜像的方法

kubectl edit deploy编辑对应的文件&#xff0c;并:wq!保存即可

微信小程序 - scroll-view组件之上拉加载下拉刷新(解决上拉加载不触发)

前言 最近在做微信小程序项目中&#xff0c;有一个功能就是做一个商品列表分页限流然后实现上拉加载下拉刷新功能&#xff0c;遇到了一个使用scroll-viwe组件下拉刷新事件始终不触发问题&#xff0c;网上很多说给scroll-view设置一个高度啥的就可以解决&#xff0c;有些人设置了…

MySQL 窗口函数

聚合函数作为窗口函数 设聚合函数为op语法结构&#xff1a; op(字段名A) over(partition by 字段名B order by 字段名C rows between D1 and D2) 其中&#xff1a; partition by&#xff1a;按照某一字段将数据进行分组 order by&#xff1a;按照某一字段将数据进行排序&…