题意

​ 给定一张 \(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(点双连通)的更多相关文章

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

  2. hdu 3686 Traffic Real Time Query System 点双两通分量 + LCA。这题有重边!!!

    http://acm.hdu.edu.cn/showproblem.php?pid=3686 我要把这题记录下来. 一直wa. 自己生成数据都是AC的.现在还是wa.留坑. 我感觉我现在倒下去床上就能 ...

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

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

  4. 【HDOJ】3686 Traffic Real Time Query System

    这题做了几个小时,基本思路肯定是求两点路径中的割点数目,思路是tarjan缩点,然后以割点和连通块作为新节点见图.转化为lca求解.结合点——双连通分量与LCA. /* 3686 */ #includ ...

  5. 【Targan+LCA】HDU 3686 Traffic Real Time Query

    题目内容 洛谷链接 给出一个\(n\)个节点,\(m\)条边的无向图和两个节点\(s\)和\(t\),问这两个节点的路径中有几个点必须经过. 输入格式 第一行是\(n\)和\(m\). 接下来\(m\ ...

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

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

  7. HDU Traffic Real Time Query System

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

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

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

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

随机推荐

  1. Spring-@ControllerAdvice 拦截异常并统一处理

    在spring 3.2中,新增了@ControllerAdvice 注解, 可以用于定义@ExceptionHandler.@InitBinder.@ModelAttribute,并应用到所有@Req ...

  2. Mysql 二进制日志备份还原

    Mysql 二进制日志备份还原 一.开启二进制日志 1.进入配置文件[mysqld]下添加配置 方案一 vim /etc/my.cnf log-bin = /usr/local/mysql/logs/ ...

  3. C#, CSV,Generic, 泛型,导出

    using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threa ...

  4. ASP.NET Core系列:读取配置文件

    1. 控制台应用 新建一个控制台应用,添加两个Package: Install-Package Microsoft.Extensions.Configuration Install-Package M ...

  5. jquery源码问题

    最近公司升级jquery版本后,原来项目中复选框的attr的使用失效,在查看了jquery的内容的时候发现版本更新,复选框的attr的使用替换成了prop,所以使用的时候出现了问题,但是涉及到的文件太 ...

  6. VUE-父组件和子组件

    1.父组件 const cnp2 = Vue.extend({ template: ` <div> <h2>我是构造器2</h2> <cpn1>< ...

  7. MVC的View本质和扩展

    一:网站启动流程简介 前面两节我们有介绍管道处理模型,然后下图总结出了mvc启动的整个流程 二:MVC返回的三种结果 从之前的流程已经反编译源码我们晓的,mvc最终都会返回一个结果,其中大概分为以下三 ...

  8. Hadoop 从节点的 NodeManager 无法启动

    一.问题描述 日志文件信息如下: -- ::, INFO nodemanager.NodeManager (LogAdapter.java:info()) - registered UNIX sign ...

  9. Linux创建高级用户并删除

    Linux创建高级用户并删除 常见window系统可以创建许多用户,但是linux也可以创建许多用户. 方法比window方便简单. (1)添加一个普通用户 :nangong(名字自己取) usera ...

  10. Linux rpm包管理工具

    1.什么是rpm包 是一种编译好的二进制软件包,安装速度快. 2.rpm包命名 el6:软件包用于在Red Hat 6.x, CentOS 6.x, and CloudLinux 6.x进行安装 el ...