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. Python学习之turtle绘图篇

    画一个红色的五角星 from turtle import * color('red','red') begin_fill() for i in range(5): fd(200) rt(144) en ...

  2. 一文了解Docker容器技术的操作

    一文了解Docker容器技术的操作 前言一.Docker是什么二.Docker的安装及测试Docker的安装Docker的Hello world测试三.Docker的常见操作镜像的基本操作容器的基本操 ...

  3. 手把手教你安装Ubuntu系统增强工具

    如果你不安装VMware增强工具的话,VMware经常会给你弹出下图的界面,提示你安装增强工具. 那么VMware增强工具到底有啥特别之处咧?其实在VMware虚拟机中安装好VMwareTools之后 ...

  4. 什么?你还不会身份证号码验证?最全的身份证正则验证js

    话不多说上代码 //身份证号合法性验证 //支持15位和18位身份证号 //支持地址编码.出生日期.校验位验证 function cidInfo(code) { var city={11:" ...

  5. DML_The OUTPUT Clause

    DML_The OUTPUT Clause /**/ ------------------------------------------------------------------------- ...

  6. TensorFlow从0到1之XLA加速线性代数编译器(9)

    加速线性代数器(Accelerated linear algebra,XLA)是线性代数领域的专用编译器.根据 https://www.tensorflow.org/performance/xla/, ...

  7. EL+Serilog日志

    简介 Elasticsearch 是一个实时的分布式搜索分析引擎,它能让你以前所未有的速度和规模,去探索你的数据. 它被用作全文检索.结构化搜索.分析以及这三个功能的组合: 安装 Elasticsea ...

  8. Redis命令速查

    目录 string list set zset hash 记录下常用的,方便查找 string 内部sds,动态扩容.小于1M加倍扩,大于1M每次扩容1M.最大长度512M. SET name val ...

  9. SLS编写规范

    SLS编写规范 规范要点说明 首先,状态的执行不可回滚,执行完了就是执行完了,并不会中断回滚,其次,状态的执行,可以反复执行,也就是说一个状态文件,可以多次来进行调用. 在编写状态文件过程中,有以下几 ...

  10. IE对于input checkbox onclick方法显示不支持此对象和方法的解决方案

    网站注册页,协议结束后,通过input checkbox勾选,进行下一步,FF没问题,IE一直显示不支持此对象和方法. 网上查找大部分说函数名称与系统函数重名,而事实上不是. <div name ...