HDU 3686 Traffic Real Time Query System

题目大意

给一个N个点M条边的无向图,然后有Q个询问X,Y,问第X边到第Y边必需要经过的点有多少个。

solution

显然园方树+tarjan求LCA,然后求两条边之间的点

必经的点的数量就是圆点的数量,然后进行分类讨论

  • 若\(LCA\)为圆点:

    那么其中一个点到\(LCA\)的圆点数量为\((deep[x] - deep[lca])/2\),因为\(LCA\)为圆点被算了两遍,所以要-1
  • 若\(LCA\)为方点:

    那么其中一个点到\(LCA\)的圆点数量为\((deep[x] - deep[lca]- 1)/2\),那么两个点之间的圆点数量就是\((deep[x] + deep[y] - 2 * deep[lca])- 1\)

由此可见,两种情况算下来,答案的式子是一样的,所以直接上板子算答案就行了,这道题的代码还是比较考验码力的……

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std; #define v e[i].to
const int maxn=10000+3,maxe=100000+3;
int n,m,tot,head[maxn],h[2*maxn],js,dfs_clock,deep[2*maxn],father[2*maxn];
int bcc_cnt,sta[maxn],top,dfn[maxn],low[maxn];
bool vis[2*maxn]; struct edge{
int from,to,next;
}e[2*maxe],ed[2*maxe]; inline void Add(int a,int b){//原图
e[++tot].from=a;
e[tot].to=b;
e[tot].next=head[a];
head[a]=tot;
} inline void Add2(int a,int b){//圆方树
ed[++js].from=a;
ed[js].to=b;
ed[js].next=h[a];
h[a]=js;
} inline void tarjan(int u){
low[u]=dfn[u]=++dfs_clock;
sta[++top]=u;
for(int i=head[u];i;i=e[i].next){
if(dfn[v]) low[u]=min(low[u],dfn[v]);
else{
tarjan(v);
low[u]=min(low[v],low[u]);
if(low[v]==dfn[u]){
++bcc_cnt;
int temp;
do{
temp=sta[top];
top--;
Add2(n+bcc_cnt,temp);
Add2(temp,n+bcc_cnt);
}while(temp!=v);
Add2(u,n+bcc_cnt);
Add2(n+bcc_cnt,u);
}
}
}
} inline void init(){
tot=0; js=0; top=0; dfs_clock=0; bcc_cnt=0;
memset(head,0,sizeof(head));
memset(e,0,sizeof(e));
memset(h,0,sizeof(h));
memset(ed,0,sizeof(ed));
memset(sta,0,sizeof(sta));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(deep,0,sizeof(deep));
memset(vis,0,sizeof(vis));
memset(father,0,sizeof(father));
memset(sta,0,sizeof(sta));
} inline void dfs(int x){
vis[x]=1;
for(int i=h[x];i;i=ed[i].next){
int now=ed[i].to;
if(vis[now]) continue;
deep[now]=deep[x]+1;
father[now]=x;
dfs(now);
}
} inline int find(int a,int b){//非倍增也可
if(deep[a]<deep[b]) swap(a,b);
while(deep[a]>deep[b]) a=father[a];
while(a!=b){
a=father[a];
b=father[b];
}
return a;
} inline int len(int a,int b){
int lca=find(a,b);
return (deep[a]+deep[b]-2*deep[lca])/2-1;
} int main(){
while(1){
scanf("%d%d",&n,&m);
if(n==0&&m==0) return 0;
init();
for(int i=1;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
Add(x,y);
Add(y,x);
}
for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
for(int i=1;i<=n+bcc_cnt;i++) if(!vis[i]) dfs(i);
int t;
scanf("%d",&t);
while(t--){
int x,y;
scanf("%d%d",&x,&y);
int a=e[x*2].from,b=e[x*2].to,c=e[y*2].from,d=e[y*2].to; //枚举节点
printf("%d\n",max(max(len(b,d),len(a,d)),max(len(b,c),len(a,c))));
}
}
}

提交语言GCC、GCC、GCC!!!

md重要的事情说三遍,淦……

HDU 3686 Traffic Real Time Query System (图论)的更多相关文章

  1. HDU 3686 Traffic Real Time Query System(双连通分量缩点+LCA)(2010 Asia Hangzhou Regional Contest)

    Problem Description City C is really a nightmare of all drivers for its traffic jams. To solve the t ...

  2. hdu 3686 Traffic Real Time Query System 点双两通分量 + LCA。这题有重边!!!

    http://acm.hdu.edu.cn/showproblem.php?pid=3686 我要把这题记录下来. 一直wa. 自己生成数据都是AC的.现在还是wa.留坑. 我感觉我现在倒下去床上就能 ...

  3. HDU 3686 Traffic Real Time Query System(点双连通)

    题意 ​ 给定一张 \(n\) 个点 \(m\) 条边的无向图,\(q\) 次询问,每次询问两边之间的必经之点个数. 思路 ​ 求两点之间必经之边的个数用的是边双缩点,再求树上距离.而对比边双和点双之 ...

  4. 【HDOJ】3686 Traffic Real Time Query System

    这题做了几个小时,基本思路肯定是求两点路径中的割点数目,思路是tarjan缩点,然后以割点和连通块作为新节点见图.转化为lca求解.结合点——双连通分量与LCA. /* 3686 */ #includ ...

  5. 【Targan+LCA】HDU 3686 Traffic Real Time Query

    题目内容 洛谷链接 给出一个\(n\)个节点,\(m\)条边的无向图和两个节点\(s\)和\(t\),问这两个节点的路径中有几个点必须经过. 输入格式 第一行是\(n\)和\(m\). 接下来\(m\ ...

  6. CH#24C 逃不掉的路 和 HDU3686 Traffic Real Time Query System

    逃不掉的路 CH Round #24 - 三体杯 Round #1 题目描述 现代社会,路是必不可少的.任意两个城镇都有路相连,而且往往不止一条.但有些路连年被各种XXOO,走着很不爽.按理说条条大路 ...

  7. HDU3686 Traffic Real Time Query System 题解

    题目 City C is really a nightmare of all drivers for its traffic jams. To solve the traffic problem, t ...

  8. Traffic Real Time Query System 圆方树+LCA

    题目描述 City C is really a nightmare of all drivers for its traffic jams. To solve the traffic problem, ...

  9. Traffic Real Time Query System HDU - 3686

    https://vjudge.net/problem/HDU-3686 点双啊,就是在求割顶的时候,另外用一个栈来存一些边 在遍历u点出发的边时,遇到树边或反向边(u,v)就把此边加入栈(可能要记一下 ...

随机推荐

  1. 关于uniapp获取当前距离屏幕顶部的距离

    onPageScroll(e){ console.log(e); }

  2. 阿里巴巴 《Java 开发者手册》+ IDEA编码插件

    4月22日,阿里巴巴发布了泰山版<Java 开发手册>,以前以为终极版就真的是终极版了,没想到还是想的太简单了,继终极版之后又发布了详尽版.华山版,这不,泰山版又来了.想想也对,行业一直在 ...

  3. 【asp.net core 系列】5 布局页和静态资源

    0. 前言 在之前的4篇的内容里,我们较为详细的介绍了路由以及控制器还有视图之间的关系.也就是说,系统如何从用户的HTTP请求解析到控制器里,然后在控制器里处理数据,并返回给视图,在视图中显示出来.这 ...

  4. AsyncTask源码解读

    AsyncTask源码解读 一.基本使用 protected void onPreExecute() protected abstract Result doInBackground(Params.. ...

  5. 第12章 Java内存模型与线程

    参考<深入理解Java虚拟机> 一.Java内存模型 1.Java内存模型 2.内存间交互操作  流程图: 3.volatile关键字 两个特性: 3.1.保证变脸对所有线程的可见性: 由 ...

  6. Vue封装公共组件TarBar

    github:https://github.com/zwnsyw/TabBar 一.实现简单思路 1.在页面底部有一个单独的TabBar组件1.1自定义TabBar组件,在APP中使用1.2让TabB ...

  7. Apollo移植

    Apollo移植 环境 平台 ubuntu16.04 Apollo_kernel 1.0 安装步骤步骤 步骤一:安装ubuntu(官方建议使用Ubuntu 14.04.3) 步骤一和步骤二参考文档路径 ...

  8. ubuntu12.04可用源

    最近试了不少源,都无法用.这一份是目前可以正常使用的 #deb cdrom:[Ubuntu 12.04.5 LTS _Precise Pangolin_ - Release amd64 (201408 ...

  9. 在CentOS7上源码安装OpenResty

    您必须将这些库perl 5.6.1+libreadlinelibpcrelibssl安装在您的电脑之中. 对于 Linux来说, 您需要确认使用 ldconfig 命令,让其在您的系统环境路径中能找到 ...

  10. jmeter正则提取器提取一个值或多个值

    [安装Dummy插件] 这个插件可以模拟服务器返回,相当于一个mockserver了. 首先安装Dummy,选项--插件管理--可选插件--Dummy. [模拟响应] 添加线程组,在线程组下添加Dum ...