题目

City C is really a nightmare of all drivers for its traffic jams. To solve the traffic problem, the mayor plans to build a RTQS (Real Time Query System) to monitor all traffic situations. City C is made up of N crossings and M roads, and each road connects two crossings. All roads are bidirectional. One of the important tasks of RTQS is to answer some queries about route-choice problem. Specifically, the task is to find the crossings which a driver MUST pass when he is driving from one given road to another given road.

Input

There are multiple test cases. 
For each test case: 
The first line contains two integers N and M, representing the number of the crossings and roads. 
The next M lines describe the roads. In those M lines, the i th line (i starts from 1)contains two integers X i and Y i, representing that road i connects crossing X i and Y i (X i≠Y i). 
The following line contains a single integer Q, representing the number of RTQs. 
Then Q lines follows, each describing a RTQ by two integers S and T(S≠T) meaning that a driver is now driving on the roads and he wants to reach roadt . It will be always at least one way from roads to roadt.
The input ends with a line of “0 0”. 
Please note that: 0<N<=10000, 0<M<=100000, 0<Q<=10000, 0<X i,Y i<=N, 0<S,T<=M

Output

For each RTQ prints a line containing a single integer representing the number of crossings which the driver MUST pass.

Sample Input

5 6
1 2
1 3
2 3
3 4
4 5
3 5
2
2 3
2 4
0 0

Sample Output

0 1

分析

大概的题目意思就是给个无向图,问从a到b的路径中有几个点必须经过。

思路:根据题意,很容易就可以想到这个题就是求a到b的路径上割点的个数。然后就可以开始缩点了。把边缩成一个点,因为每条边有且仅属于一个联通块中,然后对割点和它相邻的块建边,这样就构造了一棵树。询问a边和b边,只需要找出它们分别属于哪个块中就行,所以问题转化成了一棵树中,有些点标记了是割点,现在询问两个不为割点的点路径上有多少个割点。

这样就很容易做了,以任意一个点为树根,求出每个点到树根路径上有多少个割点,然后对于询问的两个点求一次LCA就可以求出结果了,有点小细节不多说,自己画个图就清楚了。

注意:缩点后树的点数可能是2n个。

代码

#include<cstdio>
#include <vector>
#include <algorithm>
using namespace std; const int maxn = + ;
const int maxm = + ; struct Edge {
int u, to, next, vis, id;
}edge[maxm<<]; int head[maxn<<], dfn[maxn<<], low[maxn], st[maxm], iscut[maxn], subnet[maxn], bian[maxm];
int E, time, top, btot;
vector<int> belo[maxn];
void newedge(int u, int to) {
edge[E].u = u;
edge[E].to = to;
edge[E].next = head[u];
edge[E].vis = ;
head[u] = E++;
} void init(int n) {
for(int i = ;i <= n; i++) {
head[i] = -;
dfn[i] = iscut[i] = subnet[i] = ;
belo[i].clear();
}
E = time = top = btot = ;
} void dfs(int u) {
dfn[u] = low[u] = ++time;
for(int i = head[u];i != -;i = edge[i].next) {
if(edge[i].vis) continue;
edge[i].vis = edge[i^].vis = ;
int to = edge[i].to;
st[++top] = i;
if(!dfn[to]) {
dfs(to);
low[u] = min(low[u], low[to]);
if(low[to] >= dfn[u]) {
subnet[u]++;
iscut[u] = ;
btot++;
do {
int now = st[top--];
belo[edge[now].u].push_back(btot);
belo[edge[now].to].push_back(btot);
bian[edge[now].id] = btot;
to = edge[now].u;
}while(to != u);
}
}
else
low[u] = min(low[u], low[to]);
}
} int B[maxn<<], F[maxn<<], d[maxn<<][], pos[maxn<<], tot, dep[maxn<<];
bool treecut[maxn<<];
void RMQ1(int n) {
for(int i = ;i <= n; i++) d[i][] = B[i];
for(int j = ;(<<j) <= n; j++)
for(int i = ;i + j - <= n; i++)
d[i][j] = min(d[i][j-], d[i + (<<(j-))][j-]);
} int RMQ(int L, int R) {
int k = ;
while((<<(k+)) <= R-L+) k++;
return min(d[L][k], d[R-(<<k)+][k] );
} int lca(int a, int b) {
if(pos[a] > pos[b]) swap(a, b);
int ans = RMQ(pos[a], pos[b]);
return F[ans];
} // 搜树来构造RMQ LCA
void DFS(int u) {
dfn[u] = ++time;
B[++tot] = dfn[u];
F[time] = u;
pos[u] = tot;
for(int i = head[u];i != -;i = edge[i].next){
int to = edge[i].to;
if(!dfn[to]) {
if(treecut[u])
dep[to] = dep[u] + ;
else
dep[to] = dep[u];
DFS(to);
B[++tot] = dfn[u];
}
}
} void solve(int n) {
for(int i = ;i <= n; i++) {
dfn[i] = ;
}
time = tot = ;
for(int i = ;i <= n; i++) if(!dfn[i]) {
dep[i] = ;
DFS(i);
}
RMQ1(tot);
int m, u, to;
scanf("%d", &m);
while(m--) {
scanf("%d%d", &u, &to);
u = bian[u]; to = bian[to];
if(u < || to < ) {
printf("0\n"); continue;
}
int LCA = lca(u, to);
if(u == LCA)
printf("%d\n", dep[to] - dep[u] - treecut[u]);
else if(to == LCA)
printf("%d\n", dep[u] - dep[to] - treecut[to]);
else
printf("%d\n", dep[u] + dep[to] - *dep[LCA] - treecut[LCA]);
}
} int main() {
int n, m, u, to;
while(scanf("%d%d", &n, &m) != - && n){
init(n);
for(int i = ;i <= m; i++) {
scanf("%d%d", &u, &to);
edge[E].id = i;
newedge(u, to);
edge[E].id = i;
newedge(to, u);
} for(int i = ;i <= n;i ++) if(!dfn[i]) {
dfs(i);
subnet[i]--;
if(subnet[i] <= ) iscut[i] = ;
}
int ditot = btot;
for(int i = ;i <= btot; i++) treecut[i] = ;
for(int i = ;i <= btot+n; i++) head[i] = -;
E = ;
for(int i = ;i <= n; i++) if(iscut[i]) {
sort(belo[i].begin(), belo[i].end());
ditot++;
treecut[ditot] = ;
newedge(belo[i][], ditot);
newedge(ditot, belo[i][]);
for(int j = ;j < belo[i].size(); j++) if(belo[i][j] != belo[i][j-]) {
newedge(belo[i][j], ditot);
newedge(ditot, belo[i][j]);
}
}
solve(ditot);
}
return ;
}

HDU3686 Traffic Real Time Query【缩点+lca】的更多相关文章

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

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

  2. 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 ...

  3. HDU3686 Traffic Real Time Query

    按照vdcc缩点之后一条边只会属于一个新的点集,由于这棵树上满足(不是割点) - (割点) - (不是割点)的连接方法,所以求两条边之间的必经点就是(树上距离 / 2),倍增跳lca即可 考虑到缩点后 ...

  4. HDU3686 Traffic Real Time Query System

    P.S.此题无代码,只有口胡,因为作者码炸了. 题目大意 给你一个有 \(n\) 个点, \(m\) 条边的无向图,进行 \(q\) 次询问,每次询问两个点 \(u\) \(v\),输出两个点的之间的 ...

  5. UVALive-4839 HDU-3686 Traffic Real Time Query System 题解

    题目大意: 有一张无向连通图,问从一条边走到另一条边必定要经过的点有几个. 思路: 先用tarjan将双连通分量都并起来,剩下的再将割点独立出来,建成一棵树,之后记录每个点到根有几个割点,再用RMQ求 ...

  6. 边的双联通+缩点+LCA(HDU3686)

    Traffic Real Time Query System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K ...

  7. HDU 3686 Traffic Real Time Query System (图论)

    HDU 3686 Traffic Real Time Query System 题目大意 给一个N个点M条边的无向图,然后有Q个询问X,Y,问第X边到第Y边必需要经过的点有多少个. solution ...

  8. 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 ...

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

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

随机推荐

  1. Linux (三) 基础命令 上

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一 . 背景知识 1. Linux系统中一切皆文件 在Linux系统中任何东西都是以文件形式来存储的.这 ...

  2. Java实现 LeetCode 437 路径总和 III(三)

    437. 路径总和 III 给定一个二叉树,它的每个结点都存放着一个整数值. 找出路径和等于给定数值的路径总数. 路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点 ...

  3. 第七届蓝桥杯JavaA组省赛真题

    解题代码部分来自网友,如果有不对的地方,欢迎各位大佬评论 题目1.煤球数量 煤球数目 有一堆煤球,堆成三角棱锥形.具体: 第一层放1个, 第二层3个(排列成三角形), 第三层6个(排列成三角形), 第 ...

  4. k8s学习-资源清单

    4.kubernetes使用 4.1.资源清单 api 文档.api 描述 4.1.2.说明 必须存在的属性 主要的对象 额外的参数项 例子 vim my-app.yml apiVersion: v1 ...

  5. 手把手教你用JS/Vue/React实现幸运水果机(80后情怀之作)

    项目体验地址 免费视频教程 分别使用原生JS,Vue和React,手把手教你开发一个H5小游戏,快速上手Vue和React框架的使用. 项目截图 在线体验 在线体验 游戏介绍 幸运水果机是一款街机游戏 ...

  6. shell编程(一):功能、执行、基础

    1.shell的功能 (1)自动化批量初始化系统:对N台系统初始化(装系统时对系统的时区.yum源.软件包的更新.安全的设置进行初始化) (2)自动化批量部署软件程序:(LAMP/LNMP/Tomca ...

  7. Mybatis详解(二) sqlsession的创建过程

    我们处于的位置 我们要清楚现在的情况. 现在我们已经调用了SqlSessionFactoryBuilder的build方法生成了SqlSessionFactory 对象. 但是如标题所说,要想生成sq ...

  8. 如何使用PHP生成图片

    /** * 从图片文件创建Image资源 * @param $file 图片文件,支持url * @return bool|resource 成功返回图片image资源,失败返回false */ fu ...

  9. @loj - 3157@「NOI2019」机器人

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 小 R 喜欢研究机器人. 最近,小 R 新研制出了两种机器人,分 ...

  10. Chrome浏览器 Console调试台的简单使用

    打开调试台 方法1:在chrome浏览器中打开网页,按下F12,点击下图框选内容. 方法2: 浏览器中鼠标右键选择查看网页源代码后,再按上图操作.  调试台的功能 (因为是第一次使用这个调试台,只能罗 ...