题目

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.

输入格式

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 \le 10000\), \(0 < M \le 100000\), \(0 < Q \le 10000\), \(0 < X_i\),\(Y_i \le N\), \(0 < S,T \le M\)

输出格式

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

样例输入

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

样例输出

0
1

题解

题目大意:

输出两条边之间必须经过的点

这道题其实没有什么思维难度, 显然先缩点, 求lca即可.

主要就是调起来很麻烦, 而且起点和终点不是点是边.

tarjon缩点, 倍增求lca

代码

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 1e4 + 5, M = 1e5 + 5, Lg = 25;
int n, m, qn, tot, head[2][N << 1], top, sta[N], dfsc, dfn[N], low[N], dccCnt, root, bel[N], eb[M], fa[N << 1][Lg], dep[N << 1], id[N];
bool cut[N], vis[N << 1];
vector<int> dcc[N];
struct Edge { int to, nxt, id; } edges[M << 2];
inline void add(int type, int from, int to, int eid) {
edges[++tot] = (Edge){to, head[type][from], eid}, head[type][from] = tot;
}
void tarjan(int x) {
dfn[x] = low[x] = ++dfsc;
sta[++top] = x;
if (x == root && head[0][x] == 0)
return dcc[++dccCnt].push_back(x);
int son = 0;
for (int i = head[0][x]; i; i = edges[i].nxt) {
int y = edges[i].to;
if (!dfn[y]) {
tarjan(y);
low[x] = min(low[x], low[y]);
if (dfn[x] <= low[y]) {
son++;
if (x != root || son > 1) cut[x] = 1;
dccCnt++;
while(1){
int z = sta[top--];
dcc[dccCnt].push_back(z);
if (z == y) break;
}
dcc[dccCnt].push_back(x);
}
} else low[x] = min(low[x], dfn[y]);
}
}
void dfs(int x, int fat, int depth) {
vis[x] = 1, fa[x][0] = fat, dep[x] = depth;
for (int i = 1; i <= 15; i++) fa[x][i] = fa[fa[x][i - 1]][i - 1];
for (int i = head[1][x]; i; i = edges[i].nxt) {
int y = edges[i].to;
if (vis[y]) continue;
dfs(y, x, depth + 1);
}
}
int lca(int x, int y) {
if (dep[x] < dep[y]) swap(x, y);
for (int i = 15; i >= 0; i--)
if (dep[fa[x][i]] >= dep[y]) x = fa[x][i];
if (x == y) return x;
for (int i = 15; i >= 0; i--)
if (fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
return fa[x][0];
}
int main() {
while (1) {
scanf("%d%d", &n, &m);
if (n == 0 && m == 0) break;
tot = dfsc = dccCnt = top = 0;
memset(head, 0, sizeof(head));
memset(dfn, 0, sizeof(dfn));
memset(low, 0, sizeof(low));
memset(cut, 0, sizeof(cut));
for (int x, y, i = 1; i <= m; i++) {
scanf("%d%d", &x, &y);
add(0, x, y, i), add(0, y, x, i);
}
for (int i = 1; i <= n; i++) dcc[i].clear();
for (int i = 1; i <= n; i++)
if (!dfn[i]) tarjan(root = i);
int now = dccCnt;
for (int i = 1; i <= n; i++)
if (cut[i]) id[i] = ++now;
for (int i = 1; i <= dccCnt; i++) {
for (int j = 0; j < dcc[i].size(); j++) {
int x = dcc[i][j];
if (cut[x]) add(1, id[x], i, 0), add(1, i, id[x], 0);
bel[x] = i;
}
for (int j = 0; j < dcc[i].size(); j++)
for (int k = head[0][dcc[i][j]]; k; k = edges[k].nxt) if (bel[edges[k].to] == i) eb[edges[k].id] = i;
}
memset(dep, 0, sizeof(dep));
memset(fa, 0, sizeof(fa));
memset(vis, 0, sizeof(vis));
for (int i = 1; i <= now; i++) if (!vis[i]) dfs(i, 0, 1);
scanf("%d", &qn);
for (int x, y; qn--;) {
scanf("%d%d", &x, &y);
x = eb[x], y = eb[y];
if (x == y) puts("0");
else printf("%d\n", (dep[x] + dep[y] - 2 * dep[lca(x, y)]) / 2);
}
}
return 0;
}

HDU3686 Traffic Real Time Query System 题解的更多相关文章

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

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

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

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

  3. HDU3686 Traffic Real Time Query System

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

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

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

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

  6. HDU3686 Traffic Real Time Query【缩点+lca】

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

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

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

  8. Traffic Real Time Query System,题解

    题目链接 题意: 问从一条边到另一条边的必经点. 分析: 首先,问必经点,当然是要点双缩点(圆方树)啦,关键是把边映射到哪一点上,其实直接放在某联通分量的方点上就行,但是这个点并不好找,所以我们考虑一 ...

  9. HDU Traffic Real Time Query System

    题目大意是:对于(n, m)的图,给定边a, b查询从a到b要经过的割点的最少数目. 先tarjan算法求双连通然后缩点,即对于每个割点将周围的每个双连通看成一个点与之相连.然后求解LCA即可,距离d ...

随机推荐

  1. java代码(5) ---guava之Multiset

    guava之Multiset  一.概述 Guava提供了一个新集合类型Multiset,它可以多次添加相等的元素,且和元素顺序无关,Multiset继承于JDK的Collection接口,而不是Se ...

  2. Python API自动化测试实操

    废话不多说,直接上代码截图: 我们首先来看看整个工程的目录结构,这样以便于了解项目的调用关系:config   #这里是配置包 -- base_url.py 具体配置了被测系统的url and pat ...

  3. java启动RabbitMQ消息报异常解决办法

    启动SpringCloud微服务,RabbitMQ报如下异常: 2019-08-12 18:15:49.543 ERROR 53096 --- [68.252.131:5672] o.s.a.r.c. ...

  4. mysql基础-数据库初始化操作必要步骤和客户端工具使用-记录(二)

    0x01 mysql启动时,读取配置文件的顺序 Default options are read from the following files in the given order:/etc/my ...

  5. JavaScript的for循环

    1.循环的目的 什么是循环?循环的目的是什么?循环能做什么? 举一个小例子:武汉疫情,学了JavaScript,必须拿JavaScript干点有意义的事情.我们想告诉武汉:“武汉加油,武汉挺住啊!”. ...

  6. 微信小程序 简单获取屏幕视口高度

    由于小程序的宽度是固定的 750rpx,我们可以先用wx.getSystemInfo 来获取可使用窗口的宽高(并非rpx),结合750rpx的宽度算出比例,再用比例来算出高度 let that = t ...

  7. Vue —— 精讲 VueRouter(1)

    最近被Boos调去给新人做培训去了,目前把自己整理的一些东西分享出来,希望对大家有所帮助 本章节为VueRouter前端 路由的章节部分 大纲 一.基本概念 路由就是通过网络把讯息从源地址传输到目的地 ...

  8. c++ vector基本函数、排序、查找用法

    vector用法目录: 1.基本用法 2.vector的删除操作 3.vector的sort排序 4.翻转vector中的所有元素 5.find()函数的用法 6.vector实战(这里写的是我在最开 ...

  9. MSSQL(DAC环境一下一些特殊的访问方式)

    MSSQL(在DAC环境下访问: 存储过程) Server name:      admin:计算机名\实例名                 or       admin:IP地址\实例名      ...

  10. XP系统无法进入界面 不断的反复重启-解决方法

    XP系统无法进入界面 不断的反复重启-解决方法 XP系统无法进入界面 不断的反复重启-解决方法 一般都是非正常关机导致磁盘受到损坏.需要修复磁盘. 1.插入带PE的u盘,进入PE系统后 2.win+R ...