题目

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. js中有遍历作用相关的方法详解总结

    题外话 os:个人笔记: 大概接触过map, foreach, for, filter, findIn, includes等等 字符串检索 .indexOf() 返回某个指定字符串值在字符串中首次出现 ...

  2. 查询局域网指定段内存活IP

    目录 批量ping 输出到指定文件 批量ping for /L %i IN (起始,扫描间距,结束) DO ping -w 2 -n 1 10.224.131.%i 如 for /L %i IN (5 ...

  3. test tt=0 <=>test(0)

    class test{ int mvalue; public: test(int i){ cout << "test(int i) =" << i < ...

  4. 分享一个springboot脚手架

    项目介绍 在我们开发项目的时候各个项目之间总有一些可共用的代码或者配置,如果我们每新建一个项目就把代码复制粘贴再修改就显得很没有必要.于是我就做了一个 poseidon-boot-starter 该项 ...

  5. @atcoder - AGC034F@ RNG and XOR

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个值域在 [0, 2^N) 的随机数生成器,给定参数 A[ ...

  6. brother b-PAC sdk开发包

    brother b-PAC sdk开发包 https://download.brother.com/welcome/dlfp100607/bsdkw32031eu.exe https://www.br ...

  7. python基础--函数全解析

    函数(重点) (1)初始函数 在认识函数之前,我们先做如下的需求: 让你打印10次"我爱中国,我爱祖国".我们在接触函数之前是这样写的. print('我爱中国,我爱祖国') pr ...

  8. VUE+ELEMENT-UI的后台项目封装组件--查询form的封装

    最近项目打算重构,项目的模块几乎都是以后台查询展示的传统的增删改差模式,所以卑微的我想要自己封装一下查询form,先上效果图 子组件页面: <template> <div class ...

  9. Optional 容器类

    什么是Optional容器类 Optional 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在,原来用 null 表示一个值不存在,现在 Optional 可以更好的 ...

  10. 多语言工作者の十日冲刺<10/10>

    这个作业属于哪个课程 软件工程 (福州大学至诚学院 - 计算机工程系) 这个作业要求在哪里 团队作业第五次--Alpha冲刺 这个作业的目标 团队进行Alpha冲刺--第十天(05.09) 作业正文 ...