【bzoj4242 水壶】

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。

好题。不过我太菜了做了好几个小时。

题目大意就是给你一个2000*2000的图形,在这个图形里有一些障碍,还有200000个点。

每次给你一对点,让你求这对点之间的点与点的路径中最小的最大值。

首先找两个点之间路径上边的最小的最大值,那么直接想到货车运输这道题,但是我们有的不是一颗树而是一个图。所以需要我们建边。

个人认为这个题最大的难点就在建边。

因为点数是200000级别的,先不管建完图跑什么算法,光是建边就建不了。

那么我们想一下,题目中给了一个很奇怪的图,所以我们从这个图入手。

很容易想到,不可能建出\(n^2\)条边,我们只能找一些点满足这两个点没有其他的点,再把这两个点连起来。所以现在来思博一下:我们把在这个图上的每个点看成一个小岛,并且每个小岛还能不断扩大,那么当小岛扩大到相邻时,我们就可以把这两个小岛代表的点连起来,这样的连边策略一定是最优的。

以为首先,我们保证了每个点之间都可以互相到达,其次我们要求的是最大边最小,所以尽可能的让边短一点,那就肯定是找最近的,小岛策略正好符合。

所以我们建边的方式就是BFS,将每一个点扔到队列里,再以每个点为中心向四个方向扩散,如果扩散到的点没有被标记,那么就打上标记化作这个点的领地。相反,如果扩散到的点被标记,那么我们认为这两个小岛相连了,那么就直接连一条边就行。

有考虑到会有障碍,所以在BFS的时候记一个步数就行。

建完边之后问题就变得可做了很多。

我们先跑一遍MST,然后直接倍增LCA就可以了。

细节比较多,好题。

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
const int wx=2017;
inline int read(){
int sum=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0';ch=getchar();}
return sum*f;
}
int num,tot;
int n,m,qq,p;
char c[200017];
queue<int > q;
int dx[]={0,1,0,-1,0};
int dy[]={0,0,1,0,-1};
int a[wx][wx],vis[wx][wx],dis[wx][wx];
int d[200017][21],f[200017][21],fa[200017];
int dep[4000017];
int head[4000017r];
struct node{
int l,r,d;
friend bool operator < (const node& a,const node& b){
return a.d<b.d;
}
}t[4000017];
struct e{
int nxt,to,dis;
}edge[4000017];
void add(int from,int to,int dis){
edge[++num].nxt=head[from];
edge[num].to=to;
edge[num].dis=dis;
head[from]=num;
}
int find(int x){
if(fa[x]==x)return x;
return fa[x]=find(fa[x]);
}
void bfs(){
while(q.size()){
int ux=q.front();q.pop();
int uy=q.front();q.pop();
for(int i=1;i<=4;i++){
int ex=ux+dx[i];
int ey=uy+dy[i];
if(ex<1||ex>n||ey<1||ey>m||a[ex][ey])continue;
if(dis[ex][ey]==-1){
vis[ex][ey]=vis[ux][uy];dis[ex][ey]=dis[ux][uy]+1;
q.push(ex);q.push(ey);
}
else {
if(vis[ex][ey]!=vis[ux][uy]){
t[++tot].l=vis[ux][uy];
t[tot].r=vis[ex][ey];
t[tot].d=dis[ex][ey]+dis[ux][uy];
}
}
}
}
}
void Kruskal(){
for(int i=1;i<=p;i++)fa[i]=i;
sort(t+1,t+1+tot);
for(int i=1;i<=tot;i++){
int x=find(t[i].l);int y=find(t[i].r);
if(x==y)continue;
add(x,y,t[i].d);
add(y,x,t[i].d);
fa[x]=y;
}
}
void dfs(int u,int ff,int gg){
dep[u]=dep[ff]+1;f[u][0]=ff;d[u][0]=gg;
for(int i=1;i<=20;i++){
f[u][i]=f[f[u][i-1]][i-1];
d[u][i]=max(d[u][i-1],d[f[u][i-1]][i-1]);
}
for(int i=head[u];i!=-1;i=edge[i].nxt){
int v=edge[i].to;
if(v==ff)continue;
dfs(v,u,edge[i].dis);
}
}
int FFF(int x,int y){
int maxn=0;
if(dep[x]<dep[y])swap(x,y);
for(int i=20;i>=0;i--){
if(dep[f[x][i]]>=dep[y]){
maxn=max(maxn,d[x][i]);
x=f[x][i];
}
}
if(x==y)return maxn;
for(int i=20;i>=0;i--){
if(f[x][i]!=f[y][i]){
maxn=max(maxn,d[x][i]);
maxn=max(maxn,d[y][i]);
x=f[x][i];y=f[y][i];
}
}
return max(maxn,max(d[x][0],d[y][0]));
}
int main(){
n=read();m=read();p=read();qq=read();
for(int i=1;i<=n;i++){
scanf("%s",c+1);
for(int j=1;j<=m;j++){
a[i][j]=(c[j]=='#');
}
}
memset(head,-1,sizeof head);
memset(dis,-1,sizeof dis);
// memset(d,-1,sizeof d);
for(int i=1;i<=p;i++){
int x,y;
x=read();y=read();
vis[x][y]=i;dis[x][y]=0;
q.push(x);q.push(y);
}
bfs();
Kruskal();
for(int i=1;i<=p;i++){
if(!f[i][0])dfs(i,0,0);
}
for(int i=1;i<=qq;i++){
int x,y;
x=read();y=read();
if(find(x)!=find(y))printf("-1\n");
else printf("%d\n",FFF(x,y));
}
return 0;
}

BFS+最小生成树+倍增+LCA【bzoj】4242 水壶的更多相关文章

  1. 【bzoj4242】水壶 BFS+最小生成树+倍增LCA

    题目描述 JOI君所居住的IOI市以一年四季都十分炎热著称. IOI市是一个被分成纵H*横W块区域的长方形,每个区域都是建筑物.原野.墙壁之一.建筑物的区域有P个,编号为1...P. JOI君只能进入 ...

  2. LOJ #2876. 「JOISC 2014 Day2」水壶 BFS+最小生成树+倍增LCA

    非常好的一道图论问题. 显然,我们要求城市间的最小生成树,然后查询路径最大值. 然后我们有一个非常神的处理方法:进行多源 BFS,处理出每一个城市的管辖范围. 显然,如果两个城市的管辖范围没有交集的话 ...

  3. 【CodeForces】827 D. Best Edge Weight 最小生成树+倍增LCA+并查集

    [题目]D. Best Edge Weight [题意]给定n个点m条边的带边权无向连通图,对每条边求最大边权,满足其他边权不变的前提下图的任意最小生成树都经过它.n,m<=2*10^5,1&l ...

  4. 【bzoj3732】Network 最小生成树+倍增LCA

    题目描述 给你N个点的无向图 (1 <= N <= 15,000),记为:1…N. 图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_j ( 1 & ...

  5. 训练指南 UVA - 11354(最小生成树 + 倍增LCA)

    layout: post title: 训练指南 UVA - 11354(最小生成树 + 倍增LCA) author: "luowentaoaa" catalog: true ma ...

  6. BZOJ 3732 Network —— 最小生成树 + 倍增LCA

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3732 Description 给你N个点的无向图 (1 <= N <= 15, ...

  7. BZOJ 4242: 水壶 Kruskal+BFS

    4242: 水壶 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 427  Solved: 112[Submit][Status][Discuss] D ...

  8. bzoj 4242 水壶 (多源最短路+最小生成树+启发式合并)

    4242: 水壶 Time Limit: 50 Sec  Memory Limit: 512 MBSubmit: 1028  Solved: 261[Submit][Status][Discuss] ...

  9. BZOJ 4242 水壶(BFS建图+最小生成树+树上倍增)

    题意 JOI君所居住的IOI市以一年四季都十分炎热著称. IOI市是一个被分成纵H*横W块区域的长方形,每个区域都是建筑物.原野.墙壁之一.建筑物的区域有P个,编号为1...P. JOI君只能进入建筑 ...

随机推荐

  1. 梆梆加固还原DEX文件

    0x01 先说总结: 参照https://www.cnblogs.com/jiaoxiake/p/6818786.html 最后说的步骤, 参考:https://www.52pojie.cn/thre ...

  2. 【Kth Smallest Element in a BST 】cpp

    题目: Given a binary search tree, write a function kthSmallest to find the kth smallest element in it. ...

  3. ironic baremetal rescue process

    1.用户调用Nova的rescue函数 nova/virt/ironic/driver.py class IronicDriver(virt_driver.ComputeDriver): ...... ...

  4. 编译TypeScript(TypeScript转JavaScript)

    1.配置tsconfig.json文件 tsconfig.json文件配置说明 { "compilerOptions": { //生成相关说明,TypeScript编译器如何编译. ...

  5. asp.net 存储过程 输出参数 取不到值

    这是MSDN上的明确解释:当您将 Command 对象用于存储过程时,可以将 Command 对象的 CommandType 属性设置为 StoredProcedure.当 CommandType 为 ...

  6. 【Nescafé 31】杯NOIP模拟赛

    t1 题意:n*m的棋盘上从(1,1)走到(n,m),只能向下或向右,一些格子有老鼠,每个老鼠互不相同,当处于与老鼠有重边的格子时,视为看见了这只老鼠,求到终点看到最少的不同老鼠数. 分析:DP 由于 ...

  7. GYM - 101147 B.Street

    题意: 大矩形代表市场,大矩形当中有很多小矩形样式的伞.这些小矩形都贴着大矩形的左边或者右边且互不相交.小矩形以外的地方都是阳光.求经过大矩形时在阳光下的最短时间. 题解: 最短路的做法.起点和终点与 ...

  8. 自动设置 rem es模块写法

    export default function () { let html = document.documentElement; function onWindowResize() { if (ht ...

  9. TCP面试题之HTTP和HTTPS的请求过程

    HTTP的请求过程: 1.TCP建立连接后,客户端会发送报文给服务端: 2.服务端接收报文并作出响应: 3.客户端收到响应后解析给用户: HTTPS的请求过程: 1.客户端发送请求到服务端: 2.服务 ...

  10. bzoj 3160 万径人踪灭 FFT

    万径人踪灭 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1936  Solved: 1076[Submit][Status][Discuss] De ...