【BZOJ4242】水壶(克鲁斯卡尔重构树,BFS)

题面

BZOJ然而是权限题。

Description

JOI君所居住的IOI市以一年四季都十分炎热著称。

IOI市是一个被分成纵H*横W块区域的长方形,每个区域都是建筑物、原野、墙壁之一。建筑物的区域有P个,编号为1...P。

JOI君只能进入建筑物与原野,而且每次只能走到相邻的区域中,且不能移动到市外。

JOI君因为各种各样的事情,必须在各个建筑物之间往返。虽然建筑物中的冷气设备非常好,但原野上的日光十分强烈,因此在原野上每走过一个区域都需要1单位的水。此外,原野上没有诸如自动售货机、饮水处之类的东西,因此IOI市的市民一般都携带水壶出行。大小为x的水壶最多可以装x单位的水,建筑物里有自来水可以将水壶装满。

由于携带大水壶是一件很困难的事情,因此JOI君决定携带尽量小的水壶移动。因此,为了随时能在建筑物之间移动,请你帮他写一个程序来计算最少需要多大的水壶。

现在给出IOI市的地图和Q个询问,第i个询问(1<=i<=Q)为“在建筑物Si和Ti之间移动,最小需要多大的水壶?”,请你对于每个询问输出对应的答案。

Input

第一行四个空格分隔的整数H,W,P,Q,表示IOI市被分成了纵H*横W块区域,有P个建筑物,Q次询问。

接下来H行,第i行(1<=i<=H)有一个长度为W的字符串,每个字符都是’.’或’#’之一,’.’表示这个位置是建筑物或原野,’#’表示这个位置是墙壁。

接下来P行描述IOI市每个建筑物的位置,第i行(1<=i<=P)有两个空格分隔的整数Ai和Bi,表示第i个建筑物的位置在第Ai行第Bi列。保证这个位置在地图中是’.’

接下来Q行,第i行(1<=i<=Q)有两个空格分隔的整数Si和Ti,表示第i个询问为“在建筑物Si和Ti之间移动,最小需要多大的水壶?”

Output

输出Q行,第i行(1<=i<=Q)一个整数,表示在建筑物Si和Ti之间移动最小需要多大的水壶。

如果无法到达,输出-1。此外,如果不需要经过原野就能到达,输出0。

Sample Input

5 5 4 4

.....

..##.

.#...

..#..

.....

1 1

4 2

3 3

2 5

1 2

2 4

1 3

3 4

Sample Output

3

4

4

2

HINT

1<=H<=2000

1<=W<=2000

2<=P<=2*10^5

1<=Q<=2*10^5

1<=Ai<=H(1<=i<=P)

1<=Bi<=W(1<=i<=P)

(Ai,Bi)≠(Aj,Bj)(1<=i<j<=P)

1<=Si<Ti<=P(1<=i<=Q)

题解

好神仙的一道题目啊。

很明显的一点,这道题目就是要在网格图上面计算一个最小生成树,然后就变成了货车运输一样的做法,可以倍增或者是克鲁斯卡尔重构树。

后面的部分就是原题,所以不再考虑,只考虑怎么样构造网格图最小生成树。

我们对于每一个可行的起点一起\(bfs\),对于每一个格子记录两个东西:一个记录距离当前位置最近的建筑的距离,以及是哪一个建筑。

当你\(bfs\)到某个格子的时候,发现这个格子已经被其他建筑给标记过了,那么就可以直接从距离当前这个格子最近的建筑连向距离拓展出来的格子最近的那个建筑。

然而这题卡常,边数有\(4*2000*2000\),所以开一个\(vector\)记录所有可能的距离,然后把所有的距离全部挂在上面跑。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define pi pair<int,int>
#define mp make_pair
#define fr first
#define sd second
#define MAX 2020
#define pb push_back
#define N 200200
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int H,W,P,Q;
pi p[N];
vector<pi> E[MAX*MAX];
char g[MAX][MAX];
int dis[MAX][MAX],bel[MAX][MAX];
int d[4][2]={1,0,0,1,-1,0,0,-1};
struct Line{int v,next;}e[N<<2];
int h[N<<1],cnt=1;
inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
void bfs()
{
queue<pi> Q;
for(int i=1;i<=P;++i)Q.push(p[i]),bel[p[i].fr][p[i].sd]=i;
while(!Q.empty())
{
pi u=Q.front();Q.pop();
for(int i=0;i<4;++i)
{
pi v=mp(u.fr+d[i][0],u.sd+d[i][1]);
if(g[v.fr][v.sd]=='#'||v.fr<1||v.fr>H||v.sd<1||v.sd>W)continue;
if(!bel[v.fr][v.sd])
{
Q.push(v);
bel[v.fr][v.sd]=bel[u.fr][u.sd];
dis[v.fr][v.sd]=dis[u.fr][u.sd]+1;
}
else E[dis[v.fr][v.sd]+dis[u.fr][u.sd]].pb(mp(bel[v.fr][v.sd],bel[u.fr][u.sd]));
}
}
}
int f[N<<1];
int getf(int x){return x==f[x]?x:f[x]=getf(f[x]);}
int CNT,w[N<<1],dep[N<<1];
int fa[22][N<<1];
void dfs(int u)
{
dep[u]=dep[fa[0][u]]+1;
for(int i=h[u];i;i=e[i].next)
dfs(e[i].v);
}
void Kruskal()
{
for(int i=1;i<=P;++i)f[i]=i;CNT=P;
for(int i=0;i<=H*W;++i)
for(int j=0,l=E[i].size();j<l;++j)
{
int u=getf(E[i][j].fr),v=getf(E[i][j].sd);
if(u==v)continue;++CNT;
f[CNT]=f[u]=f[v]=CNT;w[CNT]=i;
Add(fa[0][u]=CNT,u);Add(fa[0][v]=CNT,v);
}
for(int i=1;i<=21;++i)
for(int j=1;j<=CNT;++j)
fa[i][j]=fa[i-1][fa[i-1][j]];
}
int LCA(int u,int v)
{
if(dep[u]<dep[v])swap(u,v);
for(int i=21;~i;--i)
if(dep[fa[i][u]]>=dep[v])u=fa[i][u];
if(u==v)return u;
for(int i=21;~i;--i)
if(fa[i][u]!=fa[i][v])
u=fa[i][u],v=fa[i][v];
return fa[0][u];
}
int main()
{
H=read();W=read();P=read();Q=read();
for(int i=1;i<=H;++i)scanf("%s",g[i]+1);
for(int i=1;i<=P;++i)p[i].fr=read(),p[i].sd=read();
bfs();Kruskal();for(int i=CNT;i;--i)if(!dep[i])dfs(i);
int cnt=0;
while(Q--)
{
++cnt;
int u=read(),v=read();
if(getf(u)!=getf(v))puts("-1");
else printf("%d\n",w[LCA(u,v)]);
}
return 0;
}

【BZOJ4242】水壶(克鲁斯卡尔重构树,BFS)的更多相关文章

  1. [您有新的未分配科技点][BZOJ3545&BZOJ3551]克鲁斯卡尔重构树

    这次我们来搞一个很新奇的知识点:克鲁斯卡尔重构树.它也是一种图,是克鲁斯卡尔算法求最小生成树的升级版首先看下面一个问题:BZOJ3545 Peaks. 在Bytemountains有N座山峰,每座山峰 ...

  2. 洛谷P4197 Peaks&&克鲁斯卡尔重构树学习笔记(克鲁斯卡尔重构树+主席树)

    传送门 据说离线做法是主席树上树+启发式合并(然而我并不会) 据说bzoj上有强制在线版本只能用克鲁斯卡尔重构树,那就好好讲一下好了 这里先感谢LadyLex大佬的博客->这里 克鲁斯卡尔重构树 ...

  3. 洛谷 P1967 货车运输(克鲁斯卡尔重构树)

    题目描述 AAA国有nn n座城市,编号从 11 1到n nn,城市之间有 mmm 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 qqq 辆货车在运输货物, 司机们想知道每辆车在不超过车 ...

  4. 【BZOJ5415】【NOI2018】归程(克鲁斯卡尔重构树)

    [NOI2018]归程(克鲁斯卡尔重构树) 题面 洛谷 题解 我在现场竟然没有把这道傻逼题给切掉,身败名裂. 因为这题就是克鲁斯卡尔重构树的模板题啊 我就直接简单的说一下把 首先发现答案就是在只经过海 ...

  5. [note]克鲁斯卡尔重构树

    克鲁斯卡尔重构树 又叫并查集重构树 大概在NOI2018之前还是黑科技 现在?烂大街了 主要是针对图上的对边有限制的一类问题 比如每次询问一个点u不能经过边权大于w的边能走到的第k大点权是多少 也就是 ...

  6. 洛谷P4768 [NOI2018]归程(克鲁斯卡尔重构树+最短路)

    传送门 前置技能,克鲁斯卡尔重构树 我们按道路的高度建一个最大生成树,然后建好克鲁斯卡尔重构树 那么我们需要知道一颗子树内到1点距离最近是多少(除此之外到子树内任何一个点都不需要代价) 可以一开始直接 ...

  7. [模板] Kruskal算法 && 克鲁斯卡尔重构树

    克鲁斯卡尔重构树 发现没把板子放上来... 现在放一下 克鲁斯卡尔算法的正确性是利用反证法证明的. 简要地说, 就是如果不加入当前权值最小的边 \(e_1\), 那么之后加入的边和这条边会形成一个环. ...

  8. P4197 Peaks [克鲁斯卡尔重构树 + 主席树][克鲁斯卡尔重构树学习笔记]

    Problem 在\(Bytemountains\)有\(n\)座山峰,每座山峰有他的高度\(h_i\) .有些山峰之间有双向道路相连,共\(M\)条路径,每条路径有一个困难值,这个值越大表示越难走, ...

  9. P5168 xtq玩魔塔 [克鲁斯卡尔重构树+带修莫队]

    P5168 xtq玩魔塔 又是码农题- 利用克鲁斯卡尔重构树的性质 我们就可以得出 \(dep\) 值小的,肯定比 \(dep\) 大的值要优. 于是第二问就可以直接 LCA 求出来了- 至于第三问, ...

随机推荐

  1. JUC——线程同步锁(LockSupport阻塞原语)

    java.util.concurrent.locks.LockSupport这个是一个独立的类,这个类的主要功能是用来解决Thread里面提供的suspend()(挂起线程).resume()(恢复运 ...

  2. 维诺图(Voronoi Diagram)分析与实现(转)

    一.问题描述1.Voronoi图的定义又叫泰森多边形或Dirichlet图,它是由一组由连接两邻点直线的垂直平分线组成的连续多边形组成. 2.Voronoi图的特点(1)每个V多边形内有一个生成元: ...

  3. 启动Nodejs服务

    vs code 中间创建 1.  settings.json { , { , { 'Content-Type': 'text/plain;charset=utf-8' })

  4. SharpDevelop 笔记

    1. 下载地址: http://jaist.dl.sourceforge.net/project/sharpdevelop/ 2. 使用 VS2012 去掉编译不通过的 Test ,其它可以运行调试. ...

  5. R软件中 文本分析安装包 Rjava 和 Rwordseg 傻瓜式安装方法四部曲

    这两天,由于要做一个文本分析的内容,所以搜索了一天R语言中的可以做文本分析的加载包,但是在安装包的过程,真是被虐千百遍,总是安装不成功.特此专门写一篇博文,把整个心塞史畅快的释放一下. ------- ...

  6. Linux系统下安装jdk1.8

    JDK安装分为两种方式  一种是解压tar.gz配置安装, 一种是rpm安装,我这里是tar.gz安装方式 一.首先在oracle官方网下载jdk,网址如下:http://www.oracle.com ...

  7. 数据库之python操作mysql

    目录 一.pymysql 二.SQLAchemy 2.操作使用 (1)连接数据库 (2)执行原生SQL语句 (3)ORM操作-数据表操作 (4)ORM操作-数据行操作 (5)更多例子 一.pymysq ...

  8. oracle和mysql对时间与字符串的转换

    1,oracle to_date(#{item.value},'YYYY-MM-DD hh24-mi-ss') to_char(CRERATE_TIME,'YYYY-MM-DD hh24-mi-ss' ...

  9. Scrum Meeting 11.08

    成员 今日任务 明日计划 用时 徐越       赵庶宏       薄霖       卞忠昊 WebView和JavaScript交互基础 Bitmap(位图)全解析 Part1 3h  武鑫 设计 ...

  10. JAVA第一次实验 ——实验楼

    北京电子科技学院(BESTI) 实     验    报     告 课程:Java程序设计 班级:1352  姓名:潘俊洋  学号:20135230 成绩:             指导教师:娄嘉鹏 ...