HDU 3686 Traffic Real Time Query System(点双连通)
题意
给定一张 \(n\) 个点 \(m\) 条边的无向图,\(q\) 次询问,每次询问两边之间的必经之点个数。
思路
求两点之间必经之边的个数用的是边双缩点,再求树上距离。而对比边双和点双之后,我们不难发现点和边之间的对应关系,边双分量和点双分量的性质很多都是对称的。
| 边双 | 点双 |
|---|---|
| 两点之间至少有两条不共边的路径 | 两边之间至少有两条不共点的路径 |
| 边双间由桥边连接 | 点双内没有割点 |
| 边双间由桥边连接 | 点双间由割点连接 |
另外,一个点双也是一个特殊的边双,就像一个点仙人掌是一个特殊的边仙人掌一样。
那就容易看出本题就是一个点双缩点的裸题了。把所有的割点和点双分量拿出来,让每一个割点向它所在的点双分量连边即可。可能把图“缩成树”这种事本来就适合边双干,点双写起来不是很自然,也没什么办法。
代码
#include<bits/stdc++.h>
#define FOR(i, x, y) for(int i = (x), i##END = (y); i <= i##END; ++i)
#define DOR(i, x, y) for(int i = (x), i##END = (y); i >= i##END; --i)
template<typename T, typename _T> inline bool chk_min(T &x, const _T &y) {return y < x ? x = y, 1 : 0;}
template<typename T, typename _T> inline bool chk_max(T &x, const _T &y) {return x < y ? x = y, 1 : 0;}
typedef long long ll;
const int N = 10005;
const int M = 100005;
template<const int N, const int M, typename T> struct Linked_List
{
int head[N], nxt[M], tot; T to[M];
Linked_List() {clear();}
T &operator [](const int x) {return to[x];}
void clear() {memset(head, -1, sizeof(head)), tot = 0;}
void add(int u, T v) {to[tot] = v, nxt[tot] = head[u], head[u] = tot++;}
#define EOR(i, G, u) for(int i = G.head[u]; ~i; i = G.nxt[i])
};
Linked_List<N, M << 1, int> G;
Linked_List<N << 1, N << 2, int> T;
int dfn[N], low[N], stk[M], bel[M], dfn_idx, bcc, tp, tot;
bool mark[M];
int fa[N << 1], dep[N << 1], sz[N << 1], son[N << 1], top[N << 1];
int n, m, q;
void tarjan(int u, int fa_e)
{
dfn[u] = low[u] = ++dfn_idx;
EOR(i, G, u)
{
if(i == (fa_e ^ 1)) continue;
int v = G[i];
if(!dfn[v])
{
stk[++tp] = i;
tarjan(v, i), chk_min(low[u], low[v]);
if(low[v] >= dfn[u])
{
bcc++;
do bel[stk[tp] / 2] = bcc;
while(stk[tp--] != i);
}
}
else if(dfn[v] < dfn[u])
{
stk[++tp] = i;
chk_min(low[u], dfn[v]);
}
}
}
void dfs(int u, int f, int d)
{
fa[u] = f, dep[u] = d, sz[u] = 1, son[u] = 0;
EOR(i, T, u)
{
int v = T[i];
if(v == f) continue;
dfs(v, u, d + 1);
sz[u] += sz[v];
if(sz[v] > sz[son[u]]) son[u] = v;
}
}
void hld(int u, int tp)
{
top[u] = tp;
if(son[u]) hld(son[u], tp);
EOR(i, T, u)
{
int v = T[i];
if(v == fa[u] || v == son[u]) continue;
hld(v, v);
}
}
int get_lca(int u, int v)
{
while(top[u] != top[v])
{
if(dep[top[u]] < dep[top[v]]) std::swap(u, v);
u = fa[top[u]];
}
return dep[u] < dep[v] ? u : v;
}
int get_dis(int u, int v)
{
int lca = get_lca(u, v);
return dep[u] + dep[v] - 2 * dep[lca];
}
int main()
{
while(scanf("%d%d", &n, &m), (n || m))
{
G.tot = T.tot = 0;
FOR(i, 1, n) G.head[i] = -1, dfn[i] = 0;
FOR(i, 1, 2 * n) T.head[i] = -1, dep[i] = 0;
bcc = dfn_idx = tp = 0;
FOR(i, 1, m)
{
int u, v;
scanf("%d%d", &u, &v);
G.add(u, v), G.add(v, u);
}
FOR(i, 1, n) if(!dfn[i]) tarjan(i, -1);
tot = bcc;
FOR(u, 1, n)
{
tp = 0;
EOR(i, G, u)
{
if(!mark[bel[i / 2]])
{
mark[bel[i / 2]] = 1;
stk[++tp] = bel[i / 2];
}
}
if(tp >= 2)
{
tot++;
FOR(i, 1, tp) T.add(tot, stk[i]), T.add(stk[i], tot);
}
while(tp) mark[stk[tp]] = 0, tp--;
}
FOR(i, 1, tot) if(!dep[i]) dfs(i, 0, 1), hld(i, i);
scanf("%d", &q);
while(q--)
{
int e1, e2;
scanf("%d%d", &e1, &e2);
e1--, e2--;
printf("%d\n", get_dis(bel[e1], bel[e2]) / 2);
}
}
return 0;
}
HDU 3686 Traffic Real Time Query System(点双连通)的更多相关文章
- 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 ...
- hdu 3686 Traffic Real Time Query System 点双两通分量 + LCA。这题有重边!!!
http://acm.hdu.edu.cn/showproblem.php?pid=3686 我要把这题记录下来. 一直wa. 自己生成数据都是AC的.现在还是wa.留坑. 我感觉我现在倒下去床上就能 ...
- HDU 3686 Traffic Real Time Query System (图论)
HDU 3686 Traffic Real Time Query System 题目大意 给一个N个点M条边的无向图,然后有Q个询问X,Y,问第X边到第Y边必需要经过的点有多少个. solution ...
- 【HDOJ】3686 Traffic Real Time Query System
这题做了几个小时,基本思路肯定是求两点路径中的割点数目,思路是tarjan缩点,然后以割点和连通块作为新节点见图.转化为lca求解.结合点——双连通分量与LCA. /* 3686 */ #includ ...
- 【Targan+LCA】HDU 3686 Traffic Real Time Query
题目内容 洛谷链接 给出一个\(n\)个节点,\(m\)条边的无向图和两个节点\(s\)和\(t\),问这两个节点的路径中有几个点必须经过. 输入格式 第一行是\(n\)和\(m\). 接下来\(m\ ...
- CH#24C 逃不掉的路 和 HDU3686 Traffic Real Time Query System
逃不掉的路 CH Round #24 - 三体杯 Round #1 题目描述 现代社会,路是必不可少的.任意两个城镇都有路相连,而且往往不止一条.但有些路连年被各种XXOO,走着很不爽.按理说条条大路 ...
- HDU Traffic Real Time Query System
题目大意是:对于(n, m)的图,给定边a, b查询从a到b要经过的割点的最少数目. 先tarjan算法求双连通然后缩点,即对于每个割点将周围的每个双连通看成一个点与之相连.然后求解LCA即可,距离d ...
- 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 ...
- Traffic Real Time Query System 圆方树+LCA
题目描述 City C is really a nightmare of all drivers for its traffic jams. To solve the traffic problem, ...
随机推荐
- Vue.js 源码分析(二十) 指令篇 v-once指令详解
数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值,例如:<p>Message: {{ msg }}</p>以后每当msg属性发生了改变,插值处的内 ...
- Vue.js 源码分析(四) 基础篇 响应式原理 data属性
官网对data属性的介绍如下: 意思就是:data保存着Vue实例里用到的数据,Vue会修改data里的每个属性的访问控制器属性,当访问每个属性时会访问对应的get方法,修改属性时会执行对应的set方 ...
- Navicat Premium 12.0.22 安装与破解
一.安装 Navicat Premium 12.0.22的下载链接:https://pan.baidu.com/s/1swRY_fwIZfufdxDZj3hDyw 密码:09k8 安装步骤就是一路向下 ...
- 关于VS2017离线安装的一点扩充说明
转自:https://www.cnblogs.com/dunitian/p/8051985.html 其实逆天不推荐自己慢慢离线,找个离线包更新下再打包更快 Key:http://www.cnblog ...
- C#调用Activex中串口电子秤的数据,并将电子秤的数据显示到前端页面
大二的一个项目需要用到Activex技术将读取到串口中的数据在后台获取到,并将串口的数据写入数据库,这个过程需要在后台使用C#调用Activex控件已经使用的方法,然后在前端通过JavaScript进 ...
- C#开发自动照片(图片)裁剪(缩放)工具
1.需求分析 用winform窗体程序,开发一个能够自动.批量对图片进行缩放和裁剪的程序. 原本想直接从网上找类型的工具直接用,但是无奈现在网上能找到的工具,要么不能用,要么就是很 恶心的下载完后还有 ...
- C#使用HttpClient上传文件并附带其他参数
HttpClient和MultipartFormDataContent(传送门)最低适用于.NET Framework 4.5版本 发送端代码 using (HttpClient client = n ...
- 【maven】父子项目的一般姿势
一.为什么需要创建maven父子项目. 一般一个业务较多的项目,如果我们做服务拆分的话,有些公共的模块就只能做成jar包了.你将util.constant.model封装成jar包是比较好的,如果da ...
- Python项目中使用配置文件
一些讨论 Python中使用配置文件的最佳实践 Python中使用配置文件的最好方法 Python符号常量 多种配置文件方案对比 我的建议 1. 排除yaml yaml 不是一个好主意, 因为需要给项 ...
- 奖金高达150万元的NEST即将上线,速来报名
表哥.表姐们快粗来~~~分享一个劲爆消息: 年度奖金总额高达150万元的众测平台(NEST)已于2019年6月10日启动全球报名,6月26号开始首批线上众测,欢迎精英白帽们前来挑战! 更多详情请认真阅 ...