非常好的一道图论问题.

显然,我们要求城市间的最小生成树,然后查询路径最大值.

然后我们有一个非常神的处理方法:进行多源 BFS,处理出每一个城市的管辖范围.

显然,如果两个城市的管辖范围没有交集的话连边一定不是优秀的(一定会有一种都在管辖范围之内的连边方式来代替这种连边方式)

然后由于每一个点只属于一个城市的管辖范围,所以每个点只会扩展一次,这个 BFS 的复杂度是线性的.

code:

#include <bits/stdc++.h>
#define N 2006
#define M 200005
#define ll long long
using namespace std;
namespace IO {
void setIO(string s) {
string in=s+".in";
string out=s+".out";
freopen(in.c_str(),"r",stdin);
// freopen(out.c_str(),"w",stdout);
}
};
char str[N];
int n,m,P,Q,edges;
int dep[M];
int hd[M],to[M<<1],nex[M<<1],val[M<<1],vis[M],fa[18][M],Max[18][M];
int wall[N][N],id[N][N],dis[N][N],bel[N][N],p[N*N];
int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};
struct node {
int x,y;
node(int x=0,int y=0):x(x),y(y){}
};
struct edge {
int x,y;
edge(int x=0,int y=0):x(x),y(y){}
};
queue<node>q;
vector<edge>G[N*N];
void add(int u,int v,int c) {
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c;
}
void init() {
for(int i=0;i<N*N;++i) p[i]=i;
}
int find(int x) {
return p[x]==x?x:p[x]=find(p[x]);
}
int merge(int x,int y) {
x=find(x);
y=find(y);
if(x==y)
return 0;
p[x]=y;
return 1;
}
void dfs(int x,int ff) {
vis[x]=1;
fa[0][x]=ff;
dep[x]=dep[ff]+1;
for(int i=1;i<18;++i)
fa[i][x]=fa[i-1][fa[i-1][x]];
for(int i=1;i<18;++i)
Max[i][x]=max(Max[i-1][fa[i-1][x]],Max[i-1][x]);
for(int i=hd[x];i;i=nex[i]) {
int v=to[i];
if(v!=ff)
Max[0][v]=val[i],dfs(v,x);
}
}
int query(int x,int y) {
int ma=0,i,j;
if(dep[x]!=dep[y]) {
if(dep[y]<dep[x]) swap(x,y);
for(i=17;i>=0;--i) {
if(dep[fa[i][y]]>=dep[x]) {
ma=max(ma,Max[i][y]);
y=fa[i][y];
}
}
}
if(x==y) return ma;
for(i=17;i>=0;--i) {
if(fa[i][y]!=fa[i][x]) {
ma=max(ma,max(Max[i][y],Max[i][x]));
x=fa[i][x],y=fa[i][y];
}
}
return max(ma,max(Max[0][y],Max[0][x]));
}
int main() {
// IO::setIO("input");
int i,j,idx=0;
scanf("%d%d%d%d",&n,&m,&P,&Q);
for(i=1;i<=n;++i) {
scanf("%s",str+1);
for(j=1;j<=m;++j) {
id[i][j]=++idx;
wall[i][j]=(str[j]=='#');
}
}
for(i=1;i<=P;++i) {
int x,y;
scanf("%d%d",&x,&y);
bel[x][y]=i;
q.push(node(x,y));
}
while(!q.empty()) {
node e=q.front(); q.pop();
int x=e.x,y=e.y;
for(i=0;i<4;++i) {
int X=x+dx[i],Y=y+dy[i];
if(id[X][Y]&&!wall[X][Y]) {
if(!bel[X][Y]) {
bel[X][Y]=bel[x][y];
dis[X][Y]=dis[x][y]+1;
q.push(node(X,Y));
}
else if(bel[X][Y]!=bel[x][y]){
G[dis[X][Y]+dis[x][y]].push_back(edge(bel[X][Y],bel[x][y]));
}
}
}
}
init();
for(i=0;i<N*N;++i) {
for(j=0;j<G[i].size();++j) {
int u=G[i][j].x,v=G[i][j].y;
if(merge(u,v)) {
add(u,v,i);
add(v,u,i);
}
}
}
for(i=1;i<=P;++i) {
if(!vis[i]) {
dfs(i,0);
}
}
for(i=1;i<=Q;++i) {
int x,y;
scanf("%d%d",&x,&y);
if(find(x)!=find(y))
printf("-1\n");
else
printf("%d\n",query(x,y));
}
return 0;
}

  

LOJ #2876. 「JOISC 2014 Day2」水壶 BFS+最小生成树+倍增LCA的更多相关文章

  1. [LOJ#2878]. 「JOISC 2014 Day2」邮戳拉力赛[括号序列dp]

    题意 题目链接 分析 如果走到了下行车站就一定会在前面的某个车站走回上行车站,可以看成是一对括号. 我们要求的就是 类似 代价最小的括号序列匹配问题,定义 f(i,j) 表示到 i 有 j 个左括号没 ...

  2. LOJ #2877. 「JOISC 2014 Day2」交朋友 并查集+BFS

    这种图论问题都挺考验小思维的. 首先,我们把从 $x$ 连出去两条边的都合并了. 然后再去合并从 $x$ 连出去一条原有边与一条新边的情况. 第一种情况直接枚举就行,第二种情况来一个多源 bfs 即可 ...

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

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

  4. bzoj4244 & loj2878. 「JOISC 2014 Day2」邮戳拉力赛 括号序列+背包

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4244 https://loj.ac/problem/2878 题解 挺妙的一道题. 一开始一直 ...

  5. LOJ#2882. 「JOISC 2014 Day4」两个人的星座(计算几何)

    题面 传送门 题解 我们发现如果两个三角形相离,那么这两个三角形一定存在两条公切线 那么我们可以\(O(n^2)\)枚举其中一条公切线,然后可以暴力\(O(n^3)\)计算 怎么优化呢?我们可以枚举一 ...

  6. 【LOJ】#3034. 「JOISC 2019 Day2」两道料理

    LOJ#3034. 「JOISC 2019 Day2」两道料理 找出最大的\(y_{i}\)使得\(sumA_{i} + sumB_{y_i} \leq S_{i}\) 和最大的\(x_{j}\)使得 ...

  7. 【LOJ】#3033. 「JOISC 2019 Day2」两个天线

    LOJ#3033. 「JOISC 2019 Day2」两个天线 用后面的天线更新前面的天线,线段树上存历史版本的最大值 也就是线段树需要维护历史版本的最大值,后面的天线的标记中最大的那个和最小的那个, ...

  8. 「JOISC 2014 Day1」巴士走读

    「JOISC 2014 Day1」巴士走读 将询问离线下来. 从终点出发到起点. 由于在每个点(除了终点)的时间被过来的边固定,因此如果一个点不被新的边更新,是不会发生变化的. 因此可以按照时间顺序, ...

  9. 「JOISC 2014 Day1」 历史研究

    「JOISC 2014 Day1」 历史研究 Solution 子任务2 暴力,用\(cnt\)记录每种权值出现次数. 子任务3 这不是一个尺取吗... 然后用multiset维护当前的区间,动态加, ...

随机推荐

  1. Thread类的interrupted方法和isInterrupted方法的区别

    如下所示,interrupted()会改变线程的中断状态(清除),而isInterrupted()不影响线程的中断状态   /** * Tests whether the current thread ...

  2. Matplotlib数据可视化(1):入门介绍

      1 matplot入门指南¶ matplotlib是Python科学计算中使用最多的一个可视化库,功能丰富,提供了非常多的可视化方案,基本能够满足各种场景下的数据可视化需求.但功能丰富从另一方面来 ...

  3. 研发协同平台持续集成之Jenkins实践

    导读 研发协同平台有两个核心目标,一是提高研发效率 ,二是提高研发质量,要实现这两个核心目标,实现持续集成是关键之一. 什么是持续集成 在<持续集成>一书中,对持续集成的定义如下:持续集成 ...

  4. Java8尽管很香,你想过升级到Java11吗?会踩那些坑?

    目前最新JDK 11,Oracle会一直维护到2026年. Java11的新特性 1.更新支持到Unicode 10编码 Unicode 10(version 10.0 of the Unicode ...

  5. docker安装db2数据库

    查询可安装的db2镜像 # docker search db2 [root@docker-servers ~]# docker search db2 INDEX NAME DESCRIPTION ST ...

  6. js+vue、纯js 按条件分页

    听说大牛都从博客开始的... 人狠话不多,翠花上酸菜代码: 有注解基本上都看的懂!但是自己还是要注意以下几点,免得以后再浪费时间. #.vue 中监听事件 v-on:change=“vueChange ...

  7. Centos 7.5 搭建FTP配置虚拟用户

    Centos 7.5 搭建FTP配置虚拟用户 1.安装vsftpd #vsftpd下载地址 http://mirror.centos.org/centos/7/os/x86_64/Packages/v ...

  8. Linux 用户、用户组管理

    Linux系统是一个多用户多任务的分时操作系统,每个用户都有用户名(唯一).口令,用户名唯一标识该用户账号. 用户管理主要涉及到用户添加.修改和删除. 切换用户 su  用户名     su即swit ...

  9. AB实验人群定向HTE模型5 - Meta Learner

    Meta Learner和之前介绍的Casual Tree直接估计模型不同,属于间接估计模型的一种.它并不直接对treatment effect进行建模,而是通过对response effect(ta ...

  10. AD常用命令以及概念

    活动目录服务器常用命令合集如下: net accounts  查看第一台域控的计算机角色net accounts   查看计算机角色net share      查看共享netdom query fs ...