HDU3686 Traffic Real Time Query System 题解
题目
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 题解的更多相关文章
- UVALive-4839 HDU-3686 Traffic Real Time Query System 题解
题目大意: 有一张无向连通图,问从一条边走到另一条边必定要经过的点有几个. 思路: 先用tarjan将双连通分量都并起来,剩下的再将割点独立出来,建成一棵树,之后记录每个点到根有几个割点,再用RMQ求 ...
- CH#24C 逃不掉的路 和 HDU3686 Traffic Real Time Query System
逃不掉的路 CH Round #24 - 三体杯 Round #1 题目描述 现代社会,路是必不可少的.任意两个城镇都有路相连,而且往往不止一条.但有些路连年被各种XXOO,走着很不爽.按理说条条大路 ...
- HDU3686 Traffic Real Time Query System
P.S.此题无代码,只有口胡,因为作者码炸了. 题目大意 给你一个有 \(n\) 个点, \(m\) 条边的无向图,进行 \(q\) 次询问,每次询问两个点 \(u\) \(v\),输出两个点的之间的 ...
- HDU 3686 Traffic Real Time Query System (图论)
HDU 3686 Traffic Real Time Query System 题目大意 给一个N个点M条边的无向图,然后有Q个询问X,Y,问第X边到第Y边必需要经过的点有多少个. solution ...
- 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 ...
- 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 ...
- Traffic Real Time Query System 圆方树+LCA
题目描述 City C is really a nightmare of all drivers for its traffic jams. To solve the traffic problem, ...
- Traffic Real Time Query System,题解
题目链接 题意: 问从一条边到另一条边的必经点. 分析: 首先,问必经点,当然是要点双缩点(圆方树)啦,关键是把边映射到哪一点上,其实直接放在某联通分量的方点上就行,但是这个点并不好找,所以我们考虑一 ...
- HDU Traffic Real Time Query System
题目大意是:对于(n, m)的图,给定边a, b查询从a到b要经过的割点的最少数目. 先tarjan算法求双连通然后缩点,即对于每个割点将周围的每个双连通看成一个点与之相连.然后求解LCA即可,距离d ...
随机推荐
- java代码(5) ---guava之Multiset
guava之Multiset 一.概述 Guava提供了一个新集合类型Multiset,它可以多次添加相等的元素,且和元素顺序无关,Multiset继承于JDK的Collection接口,而不是Se ...
- Python API自动化测试实操
废话不多说,直接上代码截图: 我们首先来看看整个工程的目录结构,这样以便于了解项目的调用关系:config #这里是配置包 -- base_url.py 具体配置了被测系统的url and pat ...
- java启动RabbitMQ消息报异常解决办法
启动SpringCloud微服务,RabbitMQ报如下异常: 2019-08-12 18:15:49.543 ERROR 53096 --- [68.252.131:5672] o.s.a.r.c. ...
- mysql基础-数据库初始化操作必要步骤和客户端工具使用-记录(二)
0x01 mysql启动时,读取配置文件的顺序 Default options are read from the following files in the given order:/etc/my ...
- JavaScript的for循环
1.循环的目的 什么是循环?循环的目的是什么?循环能做什么? 举一个小例子:武汉疫情,学了JavaScript,必须拿JavaScript干点有意义的事情.我们想告诉武汉:“武汉加油,武汉挺住啊!”. ...
- 微信小程序 简单获取屏幕视口高度
由于小程序的宽度是固定的 750rpx,我们可以先用wx.getSystemInfo 来获取可使用窗口的宽高(并非rpx),结合750rpx的宽度算出比例,再用比例来算出高度 let that = t ...
- Vue —— 精讲 VueRouter(1)
最近被Boos调去给新人做培训去了,目前把自己整理的一些东西分享出来,希望对大家有所帮助 本章节为VueRouter前端 路由的章节部分 大纲 一.基本概念 路由就是通过网络把讯息从源地址传输到目的地 ...
- c++ vector基本函数、排序、查找用法
vector用法目录: 1.基本用法 2.vector的删除操作 3.vector的sort排序 4.翻转vector中的所有元素 5.find()函数的用法 6.vector实战(这里写的是我在最开 ...
- MSSQL(DAC环境一下一些特殊的访问方式)
MSSQL(在DAC环境下访问: 存储过程) Server name: admin:计算机名\实例名 or admin:IP地址\实例名 ...
- XP系统无法进入界面 不断的反复重启-解决方法
XP系统无法进入界面 不断的反复重启-解决方法 XP系统无法进入界面 不断的反复重启-解决方法 一般都是非正常关机导致磁盘受到损坏.需要修复磁盘. 1.插入带PE的u盘,进入PE系统后 2.win+R ...