LOJ #2876. 「JOISC 2014 Day2」水壶 BFS+最小生成树+倍增LCA
非常好的一道图论问题.
显然,我们要求城市间的最小生成树,然后查询路径最大值.
然后我们有一个非常神的处理方法:进行多源 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的更多相关文章
- [LOJ#2878]. 「JOISC 2014 Day2」邮戳拉力赛[括号序列dp]
题意 题目链接 分析 如果走到了下行车站就一定会在前面的某个车站走回上行车站,可以看成是一对括号. 我们要求的就是 类似 代价最小的括号序列匹配问题,定义 f(i,j) 表示到 i 有 j 个左括号没 ...
- LOJ #2877. 「JOISC 2014 Day2」交朋友 并查集+BFS
这种图论问题都挺考验小思维的. 首先,我们把从 $x$ 连出去两条边的都合并了. 然后再去合并从 $x$ 连出去一条原有边与一条新边的情况. 第一种情况直接枚举就行,第二种情况来一个多源 bfs 即可 ...
- 【bzoj4242】水壶 BFS+最小生成树+倍增LCA
题目描述 JOI君所居住的IOI市以一年四季都十分炎热著称. IOI市是一个被分成纵H*横W块区域的长方形,每个区域都是建筑物.原野.墙壁之一.建筑物的区域有P个,编号为1...P. JOI君只能进入 ...
- bzoj4244 & loj2878. 「JOISC 2014 Day2」邮戳拉力赛 括号序列+背包
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4244 https://loj.ac/problem/2878 题解 挺妙的一道题. 一开始一直 ...
- LOJ#2882. 「JOISC 2014 Day4」两个人的星座(计算几何)
题面 传送门 题解 我们发现如果两个三角形相离,那么这两个三角形一定存在两条公切线 那么我们可以\(O(n^2)\)枚举其中一条公切线,然后可以暴力\(O(n^3)\)计算 怎么优化呢?我们可以枚举一 ...
- 【LOJ】#3034. 「JOISC 2019 Day2」两道料理
LOJ#3034. 「JOISC 2019 Day2」两道料理 找出最大的\(y_{i}\)使得\(sumA_{i} + sumB_{y_i} \leq S_{i}\) 和最大的\(x_{j}\)使得 ...
- 【LOJ】#3033. 「JOISC 2019 Day2」两个天线
LOJ#3033. 「JOISC 2019 Day2」两个天线 用后面的天线更新前面的天线,线段树上存历史版本的最大值 也就是线段树需要维护历史版本的最大值,后面的天线的标记中最大的那个和最小的那个, ...
- 「JOISC 2014 Day1」巴士走读
「JOISC 2014 Day1」巴士走读 将询问离线下来. 从终点出发到起点. 由于在每个点(除了终点)的时间被过来的边固定,因此如果一个点不被新的边更新,是不会发生变化的. 因此可以按照时间顺序, ...
- 「JOISC 2014 Day1」 历史研究
「JOISC 2014 Day1」 历史研究 Solution 子任务2 暴力,用\(cnt\)记录每种权值出现次数. 子任务3 这不是一个尺取吗... 然后用multiset维护当前的区间,动态加, ...
随机推荐
- GTMD并查集!
徐州的A我因为并查集写错T了整场.. int find(int x){ return fa[x]==x?x:fa[x]=find(fa[x]); } GTMD!
- 曹工说Spring Boot源码(17)-- Spring从xml文件里到底得到了什么(aop:config完整解析【中】)
写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...
- num09---建造者模式
建造者模式: 核心思想:将产品 和 产品建造过程解耦
- docker集合
docker集合 docker(1):容器技术简介 docker(2):docker的“前身”—lxc docker(3):docker简介 docker(4):docker的安装(centos7)和 ...
- 小白学 Python 数据分析(7):Pandas (六)数据导入
人生苦短,我用 Python 前文传送门: 小白学 Python 数据分析(1):数据分析基础 小白学 Python 数据分析(2):Pandas (一)概述 小白学 Python 数据分析(3):P ...
- CDN&对象存储
概念 CDN是什么:名词解释不清,加快静态资源访问的技术 CDN原理:将静态资源缓存到用户所在城市 实现 步骤1:注册七牛云账号 https://portal.qiniu.com/signup?cod ...
- 一文彻底搞懂 TCP三次握手、四次挥手过程及原理
原创文章出自公众号:「码农富哥」,欢迎收藏和关注,如转载请注明出处! TCP 协议简述 TCP 提供面向有连接的通信传输,面向有连接是指在传送数据之前必须先建立连接,数据传送完成后要释放连接. 无论哪 ...
- 常用传输层协议(tcp/ip+udp)与常用应用层协议简述(http)
一.计算机网络体系结构 二.TCP与UDP差异 1.TCP是面向连接的可靠传输,UDP是面向无连接的不可靠传输 面向连接表现在3次握手,4次挥手:可靠传输表现在未进行4次挥手时的差错重传,超时重传: ...
- Go1.14发布了,快来围观新的特性啦
如期而至,Go1.14发布了,和往常一样,该版本保留了Go 1兼容性的承若,这个版本的大部分更新在工具链 .运行时库的性能提升方面,总的来说,还是在已有的基础上不断优化提成,大家期待的泛型还没有到来, ...
- 进阶之路 | 奇妙的Animation之旅
前言 本文已经收录到我的Github个人博客,欢迎大佬们光临寒舍: 我的GIthub博客 学习清单: 动画的种类 自定义View动画 View动画的特殊使用场景 属性动画 使用动画的注意事项 一.为什 ...