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维护当前的区间,动态加, ...
随机推荐
- Thread类的interrupted方法和isInterrupted方法的区别
如下所示,interrupted()会改变线程的中断状态(清除),而isInterrupted()不影响线程的中断状态 /** * Tests whether the current thread ...
- Matplotlib数据可视化(1):入门介绍
1 matplot入门指南¶ matplotlib是Python科学计算中使用最多的一个可视化库,功能丰富,提供了非常多的可视化方案,基本能够满足各种场景下的数据可视化需求.但功能丰富从另一方面来 ...
- 研发协同平台持续集成之Jenkins实践
导读 研发协同平台有两个核心目标,一是提高研发效率 ,二是提高研发质量,要实现这两个核心目标,实现持续集成是关键之一. 什么是持续集成 在<持续集成>一书中,对持续集成的定义如下:持续集成 ...
- Java8尽管很香,你想过升级到Java11吗?会踩那些坑?
目前最新JDK 11,Oracle会一直维护到2026年. Java11的新特性 1.更新支持到Unicode 10编码 Unicode 10(version 10.0 of the Unicode ...
- docker安装db2数据库
查询可安装的db2镜像 # docker search db2 [root@docker-servers ~]# docker search db2 INDEX NAME DESCRIPTION ST ...
- js+vue、纯js 按条件分页
听说大牛都从博客开始的... 人狠话不多,翠花上酸菜代码: 有注解基本上都看的懂!但是自己还是要注意以下几点,免得以后再浪费时间. #.vue 中监听事件 v-on:change=“vueChange ...
- Centos 7.5 搭建FTP配置虚拟用户
Centos 7.5 搭建FTP配置虚拟用户 1.安装vsftpd #vsftpd下载地址 http://mirror.centos.org/centos/7/os/x86_64/Packages/v ...
- Linux 用户、用户组管理
Linux系统是一个多用户多任务的分时操作系统,每个用户都有用户名(唯一).口令,用户名唯一标识该用户账号. 用户管理主要涉及到用户添加.修改和删除. 切换用户 su 用户名 su即swit ...
- AB实验人群定向HTE模型5 - Meta Learner
Meta Learner和之前介绍的Casual Tree直接估计模型不同,属于间接估计模型的一种.它并不直接对treatment effect进行建模,而是通过对response effect(ta ...
- AD常用命令以及概念
活动目录服务器常用命令合集如下: net accounts 查看第一台域控的计算机角色net accounts 查看计算机角色net share 查看共享netdom query fs ...