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, ...
随机推荐
- Python platform 模块
Python platform 模块 platform 模块用于查看当前操作系统的信息,来采集系统版本位数计算机类型名称内核等一系列信息. 使用方法: import platform # 获取操作系统 ...
- 【UOJ#388】【UNR#3】配对树(线段树,dsu on tree)
[UOJ#388][UNR#3]配对树(线段树,dsu on tree) 题面 UOJ 题解 考虑一个固定区间怎么计算答案,把这些点搞下来建树,然后\(dp\),不难发现一个点如果子树内能够匹配的话就 ...
- SQL Server中INSERT EXEC语句不能嵌套使用(转载)
问: I have three stored procedures Sp1, Sp2 and Sp3.The first one (Sp1) will execute the second one ( ...
- SpringMVC 之 上传文件
一.需求: 利用SpringMVC实现上传文件的功能 二.思路: 1.我们可以在SpringMVC中,通过配置一个MultipartResolver来上传文件. 2.通过MultipartFile f ...
- 数据库MySQL学习笔记高级篇
数据库MySQL学习笔记高级篇 写在前面 学习链接:数据库 MySQL 视频教程全集 1. mysql的架构介绍 mysql简介 概述 高级Mysql 完整的mysql优化需要很深的功底,大公司甚至有 ...
- 6. [mmc subsystem] mmc core(第六章)——mmc core主模块
一.说明 1.mmc core概述 mmc core主模块是mmc core的实现核心.也是本章的重点内容. 对应代码位置drivers/mmc/core/core.c. 其主要负责如下功能: mmc ...
- Python从零开始——模块与包
一:Python模块知识概览 二:Python模块的定义与引入 三:模块的搜素与命名空间 四:深入模块 五:模块管理——包的定义与引入
- SpringBoot整合Fastdfs,实现图片上传(IDEA)
我们部署Fastdfs,就是为了实现文件的上传. 现在使用idea整合Fastdfs,实现图片上传 部署环境:Centos7部署分布式文件存储(Fastdfs) 利用Java客户端调用FastDFS ...
- easy-copy服务器文件拷贝简易小工具
github:easy-copy import os import sys import time import paramiko as pm ''' host格式: { "ip" ...
- 1_ZedBoard开发板测试
启动 将SD卡插入电脑进行格式化 格式化时,要将SD卡格式化为FAT32文件系统.块大小格式化为4096字节时后面会出现无法启动的情况,可以先复现一下这个错误.块大小我选择4096字节. 然后将Zed ...