【BZOJ4242】水壶(克鲁斯卡尔重构树,BFS)
【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)的更多相关文章
- [您有新的未分配科技点][BZOJ3545&BZOJ3551]克鲁斯卡尔重构树
这次我们来搞一个很新奇的知识点:克鲁斯卡尔重构树.它也是一种图,是克鲁斯卡尔算法求最小生成树的升级版首先看下面一个问题:BZOJ3545 Peaks. 在Bytemountains有N座山峰,每座山峰 ...
- 洛谷P4197 Peaks&&克鲁斯卡尔重构树学习笔记(克鲁斯卡尔重构树+主席树)
传送门 据说离线做法是主席树上树+启发式合并(然而我并不会) 据说bzoj上有强制在线版本只能用克鲁斯卡尔重构树,那就好好讲一下好了 这里先感谢LadyLex大佬的博客->这里 克鲁斯卡尔重构树 ...
- 洛谷 P1967 货车运输(克鲁斯卡尔重构树)
题目描述 AAA国有nn n座城市,编号从 11 1到n nn,城市之间有 mmm 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 qqq 辆货车在运输货物, 司机们想知道每辆车在不超过车 ...
- 【BZOJ5415】【NOI2018】归程(克鲁斯卡尔重构树)
[NOI2018]归程(克鲁斯卡尔重构树) 题面 洛谷 题解 我在现场竟然没有把这道傻逼题给切掉,身败名裂. 因为这题就是克鲁斯卡尔重构树的模板题啊 我就直接简单的说一下把 首先发现答案就是在只经过海 ...
- [note]克鲁斯卡尔重构树
克鲁斯卡尔重构树 又叫并查集重构树 大概在NOI2018之前还是黑科技 现在?烂大街了 主要是针对图上的对边有限制的一类问题 比如每次询问一个点u不能经过边权大于w的边能走到的第k大点权是多少 也就是 ...
- 洛谷P4768 [NOI2018]归程(克鲁斯卡尔重构树+最短路)
传送门 前置技能,克鲁斯卡尔重构树 我们按道路的高度建一个最大生成树,然后建好克鲁斯卡尔重构树 那么我们需要知道一颗子树内到1点距离最近是多少(除此之外到子树内任何一个点都不需要代价) 可以一开始直接 ...
- [模板] Kruskal算法 && 克鲁斯卡尔重构树
克鲁斯卡尔重构树 发现没把板子放上来... 现在放一下 克鲁斯卡尔算法的正确性是利用反证法证明的. 简要地说, 就是如果不加入当前权值最小的边 \(e_1\), 那么之后加入的边和这条边会形成一个环. ...
- P4197 Peaks [克鲁斯卡尔重构树 + 主席树][克鲁斯卡尔重构树学习笔记]
Problem 在\(Bytemountains\)有\(n\)座山峰,每座山峰有他的高度\(h_i\) .有些山峰之间有双向道路相连,共\(M\)条路径,每条路径有一个困难值,这个值越大表示越难走, ...
- P5168 xtq玩魔塔 [克鲁斯卡尔重构树+带修莫队]
P5168 xtq玩魔塔 又是码农题- 利用克鲁斯卡尔重构树的性质 我们就可以得出 \(dep\) 值小的,肯定比 \(dep\) 大的值要优. 于是第二问就可以直接 LCA 求出来了- 至于第三问, ...
随机推荐
- 关于springcloud的一些问题总结.txt
@Bean public CorsFilter corsFilter() { final UrlBasedCorsConfigurationSource source = new UrlBasedCo ...
- appium 元素定位方法汇总
以上图为例,要定位到右下角的 我的 ,并点击 # appium的webdriver提供了11种元素定位方法,在selenium的基础上扩展了三个,可以在pycharm里面输入driver.find_e ...
- 关于MySql数据库主键及索引的区别
一.什么是索引?索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存.如果没有索引,执行查询时MySQL必须从第一个记录开始扫描整个表的所有记录,直至找到符合要求的记录.表里 ...
- CHAPTER 25 The Greatest Show on Earth 第25章 地球上最壮观的演出
CHAPTER 25 The Greatest Show on Earth 第25章 地球上最壮观的演出 Go for a walk in the countryside and you will f ...
- thrift0.5入门操作
在探索未知的程序之前,我们往往会使用“Hello World”这个经典的输出作为测试,为了遵循这个惯例,作为thrift菜鸟都不算的一员,决定跑一下“Hello world”正式进入菜鸟的行列. th ...
- PASSWORD MySQL 5.6.21-1ubuntu14.04_amd64
/***************************************************************************** The main idea is that ...
- shell之arp命令
arp: 显示所有的表项. arp -d address: 删除一个arp表项. arp -s address hw_addr: 设置一个arp表项. 常用参数: -a 使用bsd形式输出.(没有 ...
- jsweb常用代码
<script> $(function (){ $.ajax({ url: 'https://test.com:8080/api/v1/users?query_not_auth=100&a ...
- 实验三 敏捷开发和XP实验
课程:Java程序设计实验 班级:1352 姓名: 于佳心 学号:20135206 成绩: 指导教师:娄嘉鹏 ...
- 课堂练习 psp表
项目计划总结表: 日期 编程 完善程序 测试程序 参考资料 日总结 3.20 18:00---19:30 1.5 3.21 9:30----10:00 10:00---10:30 ...