题目

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. spring Cloud服务注册中心Eureka集群

    spring Cloud服务注册中心Eureka集群配置: 在application.yml文件加以下配置: server: port: 8761 tomcat: uri-encoding: UTF- ...

  2. 从linux源码看socket(tcp)的timeout

    从linux源码看socket(tcp)的timeout 前言 网络编程中超时时间是一个重要但又容易被忽略的问题,对其的设置需要仔细斟酌.在经历了数次物理机宕机之后,笔者详细的考察了在网络编程(tcp ...

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

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

  4. Nice Jquery Validator 常用规则整理

    一些简单规则 numeric: [/^[0-9]*$/, '请填写数值'], money: [/^(?:0|[1-9]\d*)(?:\.\d{1,2})?$/, "请填写有效的金额" ...

  5. sublime安装ctags用于追踪函数

    1.下载最新的ctags到非中文目录,这里,我们推荐c:\windows\system32,ctags可从http://ctags.sourceforge.net/下载,最后更新是在09年,版本5.8 ...

  6. java中工厂模式

    最近在项目中使用了工厂模式来重构下之前的代码,在这里做个小结. 工厂模式最主要的特点是每次新增一个产品的时候,都需要新增一个新的工厂,这样在对于新的产品做扩展的时候,减少对客户端代码的修改. 我在项目 ...

  7. SQL去掉重复数据

    SELECT vc_your_email,vc_our_ref_or_code INTO #tmp FROM( SELECT vc_your_email,vc_our_ref_or_code,ROW_ ...

  8. Windows 程序设计(4) MFC-02 基本控件-上

    1. Button 按钮控件 1.1.按钮控件的基本使用 新建对话框工程,拖拽按钮控件,添加点击事件响应函数! a.双击模版进行添加: b.事件方式进行添加: button的常见事件类型 void C ...

  9. cb19a_c++_只适合string类型的操作_提取_追加_替换

    *cb19a_c++_只适合string类型的操作_提取_追加_替换三个substr重载函数-获取一个字符串的一部分六个append重载函数-追加字符十个replace重载函数-替换更换 重载函数越多 ...

  10. 010.OpenShift综合实验及应用

    实验一 安装OpenShift 1.1 前置准备 [student@workstation ~]$ lab review-install setup 1.2 配置规划 OpenShift集群有三个节点 ...