BZOJ2167 : 公交车站
设$f[i]$表示$i$往上通过一趟公交车能到达的深度最小的祖先,这可以通过将公交车按$lca$深度从小到大排序后用并查集染色得到。
对于每个询问:
$1.x==y$
$ans=0$。
$2.x$是$y$的祖先
交换$x,y$,变成$3$。
$3.y$是$x$的祖先:
在$f$上倍增即可。
$4.x->lca->y$
首先倍增求出一步就能到$lca$的那个点$t$,然后沿着$lca$往下贪心爬一步到达$z$,再加上$z$到$y$的距离。
找$z$的时候,考虑二分查找,那么只需要判断两个点之间是否可以只用一条公交线路到达。
这等价于判断是否有公交线路起点在$t$子树内,终点在$z$子树内,可持久化线段树维护。
时间复杂度$O(n\log^2n)$。
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=10010,K=15,M=320010;
int n,m,Q,i,j,x,y,z,g[N],v[N<<1],nxt[N<<1],ed,G[N],V[N<<1],NXT[N<<1],ED;
int p[N],fa[N][K],f[N],d[N],size[N],son[N],st[N],en[N],dfn,q[N],top[N];
int T[N],l[M],r[M],val[M],tot;
struct E{int x,y,z;}e[N];
inline bool cmp(const E&a,const E&b){return d[a.z]<d[b.z];}
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
inline void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
inline void ADD(int x,int y){V[++ED]=y;NXT[ED]=G[x];G[x]=ED;}
void dfs(int x){
size[x]=1;d[x]=d[f[x]]+1;
for(int i=g[x];i;i=nxt[i])if(v[i]!=f[x]){
f[v[i]]=x;
dfs(v[i]),size[x]+=size[v[i]];
if(size[v[i]]>size[son[x]])son[x]=v[i];
}
}
void dfs2(int x,int y){
q[st[x]=++dfn]=x;top[x]=y;
if(son[x])dfs2(son[x],y);
for(int i=g[x];i;i=nxt[i])if(v[i]!=son[x]&&v[i]!=f[x])dfs2(v[i],v[i]);
en[x]=dfn;
}
inline int lca(int x,int y){
for(;top[x]!=top[y];x=f[top[x]])if(d[top[x]]<d[top[y]])swap(x,y);
return d[x]<d[y]?x:y;
}
inline int up(int x,int k){
while(1){
int t=st[x]-st[top[x]];
if(k<=t)return q[st[x]-k];
k-=t+1;
x=f[top[x]];
}
}
inline int go(int x,int y){
if(x==y)return 0;
if(d[fa[x][K-1]]>d[y])return -1;
int t=1;
for(int i=K-1;~i;i--)if(d[fa[x][i]]>d[y])x=fa[x][i],t+=1<<i;
return t;
}
int ins(int x,int a,int b,int c){
int y=++tot;
val[y]=val[x]+1;
if(a==b)return y;
int mid=(a+b)>>1;
if(c<=mid)l[y]=ins(l[x],a,mid,c),r[y]=r[x];else l[y]=l[x],r[y]=ins(r[x],mid+1,b,c);
return y;
}
int ask(int x,int a,int b,int c,int d){
if(c<=a&&b<=d)return val[x];
int mid=(a+b)>>1,t=0;
if(c<=mid)t=ask(l[x],a,mid,c,d);
if(d>mid)t+=ask(r[x],mid+1,b,c,d);
return t;
}
inline bool check(int x,int y){return ask(T[en[x]],1,n,st[y],en[y])>ask(T[st[x]-1],1,n,st[y],en[y]);}
inline int query(int x,int y){
if(st[x]<=st[y]&&en[y]<=en[x])return go(y,x);
if(st[y]<=st[x]&&en[x]<=en[y])return go(x,y);
int z=lca(x,y),t=0;
if(d[fa[x][K-1]]>d[z])return -1;
for(int i=K-1;~i;i--)if(d[fa[x][i]]>d[z])x=fa[x][i],t+=1<<i;
int l=0,r=d[y]-d[z]-1,mid,o=d[y]-d[z];
while(l<=r)if(check(x,up(y,mid=(l+r)>>1)))r=(o=mid)-1;else l=mid+1;
o=go(y,up(y,o));
if(o<0)return -1;
return t+o+1;
}
void dfs3(int x){
for(int i=1;i<K;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
for(int i=g[x];i;i=nxt[i])if(v[i]!=f[x])dfs3(v[i]);
}
int F(int x){return p[x]==x?x:p[x]=F(p[x]);}
inline void col(int x,int y){for(x=F(x);d[x]>=d[y];x=F(x))fa[x][0]=y,p[x]=f[x];}
int main(){
read(n),read(m),read(Q);
for(i=1;i<n;i++)read(x),read(y),add(x,y),add(y,x);
dfs(1);
dfs2(1,1);
for(i=1;i<=m;i++){
read(e[i].x),read(e[i].y),e[i].z=lca(e[i].x,e[i].y);
x=e[i].x,y=e[i].y,z=e[i].z;
if(x==y)continue;
ADD(st[x],st[y]);
ADD(st[y],st[x]);
}
sort(e+1,e+m+1,cmp);
for(i=1;i<=n;i++)p[i]=fa[i][0]=i;
for(i=1;i<=m;i++)col(e[i].x,e[i].z),col(e[i].y,e[i].z);
dfs3(1);
for(i=1;i<=n;i++)for(T[i]=T[i-1],j=G[i];j;j=NXT[j])T[i]=ins(T[i],1,n,V[j]);
while(Q--){
read(x),read(y);
z=query(x,y);
if(z>0)z--;
printf("%d\n",z);
}
return 0;
}
BZOJ2167 : 公交车站的更多相关文章
- springboot整合jsp,完成公交车站路线图
转: springboot整合jsp,完成公交车站路线图 点赞再看,养成习惯 开发环境: jdk 8 intellij idea tomcat 8 mysql 5.7 maven 3.6 所用技术: ...
- bzoj 2167: 公交车站
Description Z市交通不发达,所有公交路线覆盖的边竟然一个环也不包含,甚至该市的公交路线有可能会分为几个互不连通的块,这可真是不可思议.有一天,你突然听到一条消息,说你的M个同学被困在了Z市 ...
- BZOJ 2004 Bus 公交线路(矩阵)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2004 题意:小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依 ...
- bzoj 2004: [Hnoi2010]Bus 公交线路
Description 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距 离均为1km. 作为公交车线路的规划者,小Z调查了市民的需求,决 ...
- 杭州富阳场口科目四考试公交路线(西溪北苑->场口)
从西溪北苑出发,时间充裕,比较悠闲,打算坐公交前往,也打算做下科目四模拟题,顺便欣赏沿途的风景(去的时候需要看题目,回来的时候可以放松,哈哈哈),路线如下. 早上7点半出发,出去吃个早餐,步行到文一社 ...
- 【BZOJ2004】[Hnoi2010]Bus 公交线路 状压+矩阵乘法
[BZOJ2004][Hnoi2010]Bus 公交线路 Description 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距离均为1 ...
- BZOJ2004:[HNOI2010]Bus 公交线路(状压DP,矩阵乘法)
Description 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距离均为1km. 作为公交车线路的规划者,小Z调查了市民的需求,决定 ...
- 【bzoj2004】[Hnoi2010]Bus 公交线路 状压dp+矩阵乘法
题目描述 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距离均为1km. 作为公交车线路的规划者,小Z调查了市民的需求,决定按下述规则设计 ...
- bzoj2004 [Hnoi2010]公交线路
Description 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距 离均为1km. 作为公交车线路的规划者,小Z调查了市民的需求,决 ...
随机推荐
- Python-数据类型之数字
一:数字类型概述 数字提供了标量存储和直接访问,属于不可变数据类型,所谓不可变,我们可以认为,更改数字的值会生成一个新的对象 # id可以唯一表示一个对象 age =18 print(id(age)) ...
- hive表中字段显示为NULL时,HDFS文件中存储为\N
hive数据落地到hdfs,null会默认用'\N'存储 解决方式1:利用命令(这个我没起效果) alter table adl_cici_test_fdt set serdeproperties(' ...
- snmp v3的安全配置 snmp认证与加密配置(53)
http://www.ttlsa.com/zabbix/snmp-v3-configuration/
- [转] HTML5+规范:device(管理设备信息)
http://blog.csdn.net/qq_27626333/article/details/51815310 Device模块管理设备信息,用于获取手机设备的相关信息,如IMEI.IMSI.型号 ...
- Angularjs 学习笔记-2017-02-06-双向数据绑定
NG: ng-bind: 标签属性 ng-bind=" obj.xxx " ,不会出现 用于区别{{ }} 标签,当页面未加载完毕时可以看到{{}}标签,非常不雅观,ng-bi ...
- css3三角形冒泡泡图形制作
图一: 图二: <!DOCTYPE html> <html> <head> <title>css 三角形</title> <style ...
- alpha冲刺1/10
目录 摘要 团队部分 个人部分 摘要 队名:小白吃 组长博客:hjj 作业博客:来自双十一的爱 团队部分 后敬甲(组长) 过去两天完成了哪些任务 文字描述 Alpha版本的任务细分安排 leangoo ...
- 原 HTML5 requestFullScreen&exitFullscreen全屏兼容方案
摘要: html5 video全屏实现方式 首先来说,这个标题具有误导性,但这样设置改标题也是主要因为video使用的比较多 在html5中,全屏方法可以适用 ...
- 求小于n且与n互质的数的个数
int eu(int n){ int ans=n; for(int i=2;i*i<=n;i++) { if(n%i==0) { ans=ans/i*(i-1); while(n%i==0)n/ ...
- Windows 下安装 Ubuntu 双系统(更新)
Windows + Ubuntu 16.04 ---> 双系统 前言:本篇文章是对之前文章的更新,更新的主内容是把原来用手机拍摄的图片换成了虚拟机的截图,以及对磁盘划分的新的见解和一些使用感受, ...