对于任意两个建筑物,以它们之间的最短路为边权求出最小生成树。

则询问(x,y)的答案为最小生成树上x到y路径上边权的最大值。

BFS求出离每个点最近的建筑物以及到它的距离,可以发现只有交界处的边才有用,用这些边求MST即可。

#include<cstdio>
#include<algorithm>
using namespace std;
const int L=2010,N=200010,K=17,inf=~0U>>1;
int H,W,n,m,Q,i,j,x,y,z,p,mx;
int dis[L][L][2],q[L*L][2],h=1,t;
int fa[N],g[N],v[N<<1],w[N<<1],nxt[N<<1],ed,f[N][K+1],fm[N][K+1],d[N];
char s[L];bool a[L][L],vis[L][L];
struct E{int x,y;E*nxt;}*e[L*L],pool[L*L],*cur=pool;
inline void up(int&a,int b){if(a<b)a=b;}
inline void bfs(int x,int y,int z,int p){
if(x<1||x>H||y<1||y>W||vis[x][y]||!a[x][y])return;
vis[x][y]=1,dis[x][y][0]=z,dis[x][y][1]=p,q[++t][0]=x,q[t][1]=y;
}
inline void check(int a,int b,int c,int d){
if(vis[a][b]&&vis[c][d]&&dis[a][b][1]!=dis[c][d][1]){
int x=dis[a][b][0]+dis[c][d][0];
E*p=cur++;p->x=dis[a][b][1];p->y=dis[c][d][1];p->nxt=e[x];e[x]=p;
up(mx,x);
}
}
int F(int x){return fa[x]==x?x:fa[x]=F(fa[x]);}
inline void add(int x,int y,int z){v[++ed]=y;w[ed]=z;nxt[ed]=g[x];g[x]=ed;}
void dfs(int x,int pre,int dis){
f[x][0]=pre,fm[x][0]=dis;d[x]=d[pre]+1;
for(int i=1;i<=K;i++)f[x][i]=f[f[x][i-1]][i-1],fm[x][i]=max(fm[x][i-1],fm[f[x][i-1]][i-1]);
for(int i=g[x];i;i=nxt[i])if(v[i]!=pre)dfs(v[i],x,w[i]);
}
inline int ask(int x,int y){
if(F(x)!=F(y))return -1;
int t=0,i;
if(d[x]<d[y])swap(x,y);
for(i=K;~i;i--)if(d[f[x][i]]>=d[y])up(t,fm[x][i]),x=f[x][i];
if(x==y)return t;
for(i=K;~i;i--)if(f[x][i]!=f[y][i])up(t,max(fm[x][i],fm[y][i])),x=f[x][i],y=f[y][i];
return max(t,max(fm[x][0],fm[y][0]));
}
inline void read(int&a){char ch;while(!(((ch=getchar())>='0')&&(ch<='9')));a=ch-'0';while(((ch=getchar())>='0')&&(ch<='9'))(a*=10)+=ch-'0';}
int main(){
read(H),read(W),read(n),read(Q);
for(i=1;i<=H;i++)for(scanf("%s",s+1),j=1;j<=W;j++)a[i][j]=s[j]=='.';
for(i=1;i<=n;i++)read(x),read(y),bfs(x,y,0,i),fa[i]=i;
while(h<=t){
x=q[h][0],y=q[h++][1],z=dis[x][y][0]+1,p=dis[x][y][1];
bfs(x-1,y,z,p),bfs(x+1,y,z,p),bfs(x,y-1,z,p),bfs(x,y+1,z,p);
}
for(i=1;i<=H;i++)for(j=1;j<W;j++)check(i,j,i,j+1);
for(i=1;i<H;i++)for(j=1;j<=W;j++)check(i,j,i+1,j);
for(i=0;i<=mx;i++)for(E*p=e[i];p;p=p->nxt)if(F(p->x)!=F(p->y))add(p->x,p->y,i),add(p->y,p->x,i),fa[fa[p->x]]=fa[p->y];
for(i=1;i<=n;i++)if(!d[i])dfs(i,0,0);
while(Q--)read(x),read(y),printf("%d\n",ask(x,y));
return 0;
}

  

BZOJ4242 : 水壶的更多相关文章

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

    [bzoj4242 水壶] Description JOI君所居住的IOI市以一年四季都十分炎热著称. IOI市是一个被分成纵H*横W块区域的长方形,每个区域都是建筑物.原野.墙壁之一.建筑物的区域有 ...

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

    [BZOJ4242]水壶(克鲁斯卡尔重构树,BFS) 题面 BZOJ然而是权限题. Description JOI君所居住的IOI市以一年四季都十分炎热著称. IOI市是一个被分成纵H*横W块区域的长 ...

  3. 最小生成树Kruskal+LCA+bfs【bzoj4242】水壶

    Description JOI 君所居住的 IOI 市以一年四季都十分炎热著称. IOI 市被分成 \(H\) 行,每行包含 \(W\) 块区域.每个区域都是建筑物.原野.墙壁之一. IOI 市有 \ ...

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

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

  5. 「BZOJ4242」水壶

    题目链接 戳我 \(Solution\) 我们看到这题之后发现这题不是\(n^2\)把边弄出来后就跟货车运输差不多了,但是看了数据后发现\(n^2\)条边建不出来啊,这里就不详细的讲\(kruskal ...

  6. [Swift]LeetCode365. 水壶问题 | Water and Jug Problem

    You are given two jugs with capacities x and y litres. There is an infinite amount of water supply a ...

  7. loj2876 水壶 [JOISC 2014 Day2] kruscal重构树

    正解:kruscal重构树+bfs 解题报告: 我永远喜欢loj! 感觉这题和这题挺像的,,,预处理和解题方法都是,,,所以大概整体二分能过去? 但因为做这题主要是入门一下kruscal重构树,,,所 ...

  8. 水壶-[Kruskal重构树] [解题报告]

    水壶 本来从不写针对某题的题解,但因为自己实在是太蠢了,这道题也神TM的恶心,于是就写篇博客纪念一下 H水壶 时间限制 : 50000 MS 空间限制 : 565536 KB 评测说明 : 2s,51 ...

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

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

随机推荐

  1. CF876 F 思维 枚举

    给你n个数,问有几个区间满足,区间内或操作大于区间内的任意数. 首先可以知道,两数或操作的结果必定不会小于两者间的最大值,也就是说对于一个区间中,不合法的状态只有两值或相等.那么我们可以考虑枚举每个数 ...

  2. elementUI下拉框错误记录

    选择广东省深圳市,保存,再编辑是这样效果 原因 保存的那张表相关字段为字符串,而生成下拉框该字段是整数,两者改成一致即可 修改后

  3. Java SSM框架之MyBatis3(四)MyBatis之一对一、一对多、多对多

    项目搭建Springboot 1.5  pom.xml <?xml version="1.0" encoding="UTF-8"?> <pro ...

  4. mybatis一对多关联查询——(九)

    1.需求: 查询所有订单信息及订单下的订单明细信息. 订单信息与订单明细为一对多关系. 2.      sql语句 确定主查询表:订单表 确定关联查询表:订单明细表 在一对一查询基础上添加订单明细表关 ...

  5. mybatis输入输出映射——(五)

    0.#{}与${}区别 #{}实现的是向prepareStatement中的预处理语句中设置参数值,sql语句中#{}表示一个占位符即?. <!-- 根据id查询用户信息 --> < ...

  6. Redis配置文件介绍

    Redis在源码包中存放了一个Redis配置实例文件,文件中对各个配置点进行了简单的介绍,我也通过这个文件来对Redis的一些配置进行一些简单介绍. 一.UNITS(单位)[了解] 1.Redis服务 ...

  7. gbk文件转为utf8文件

    convmv -f gbk -t utf- --notest -r ./

  8. .net的锁

    一.lock .Monitor  处理并行任务的时候,效率最高的就是多线程.当不同线程需要访问同一资源时候,就需要同步了.就像生活中很多人要一起赶飞机大家都要访问飞机这个资源每个人是一条线程那么就有门 ...

  9. java iterator(迭代器)

    任何容器类,都必须有某种方式可以插入元素并将它们再次取出,毕竟持有事物是容器最基本的工作,对于List,add()插入fang,get()取出,如果从更高层的角度思考,会发现这里有个确定:要用容器,必 ...

  10. (三)发布Dubbo服务

    我们现在来学习下发布Dubbo服务,主要参考dubbo开发包里的demo源码:由浅入深的讲解下这个小demo: github地址:https://github.com/apache/incubator ...