非常好的一道图论问题.

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

然后我们有一个非常神的处理方法:进行多源 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. pthread_cond_broadcast & pthread_cond_signal

    pthread_cond_broadcast(&cond1)的作用是唤醒所有正在pthread_cond_wait(&cond1,&mutex1)的线程. pthread_co ...

  2. Qt使用双缓冲绘图时报错:pure virtual method called

    这个问题折磨了我将近四个小时. 起始原因是想写一个双缓冲绘图的画板,大概看了一下网上的教程,理解双缓冲绘图的思想后,没有完全参照网上的步骤,想着用自己的思路实现一下.(其实和网上的教程也没有太大差别) ...

  3. win10CPU版TensorFlow安装详细流程(踩N个坑之后的总结)

    版本说明: 多次实验后,python3.5+TensorFlow1.2+numpy1.16.4比较成功,不会报奇奇怪怪的错.(安装流程中会说到,不需要提前下载) 准备工作: 找到电脑:C:\Users ...

  4. sparc v8 汇编语言语法

    1.3.1 Labeling Format Symbol names beginning with a dot (.) are assumed to be local symbols. Names b ...

  5. NOIP2012-------跳石头(C语言)

    #include<stdio.h> ]; int check(long mid, long n, long m) { long last, i, ans; last = a[]; ans ...

  6. vscode安装使用

    1.新建文件:cmd+n2.设置默认浏览器: https://blog.csdn.net/zSY_snake/article/details/83449571 3.view in browser不支持 ...

  7. 怎么用IDEA快速查看类图关系

    做Java开发的,现在普遍都用上idea了.可以说,idea是当之无愧的Java开发神器.如果,你现在还没用idea,那肯定是你还没有感受过它的强大. 好了,话不多说,今天的主题主要是教大家怎么通过i ...

  8. linux中权限管理命令(chmod/chown/chgrp/unmask)

    目录 chmod chown chgrp umask chmod 解释 命令名称:chmod 命令英文原意:change the permissions mode of a file 命令所在路径:/ ...

  9. POJ 1753 Flip Game 暴力 深搜

    Flip Game Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 59468   Accepted: 24750 Descr ...

  10. java设计模式4——原型模式

    java设计模式4--原型模式 1.写在前面 本节内容与C++语言的复制构造函数.浅拷贝.深拷贝极为相似,因此建议学习者可以先了解C++的该部分的相关知识,或者学习完本节内容后,也去了解C++的相应内 ...