HDU3686 Traffic Real Time Query
按照vdcc缩点之后一条边只会属于一个新的点集,由于这棵树上满足(不是割点) - (割点) - (不是割点)的连接方法,所以求两条边之间的必经点就是(树上距离 / 2),倍增跳lca即可
考虑到缩点后树上点数的编号可能超过n,所以与树有关的数组开两倍N
又是一个模板
Code:
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std; const int N = 1e4 + ;
const int M = 1e5 + ;
const int Lg = ; int n, m, qn, tot, head[][N << ], top, sta[N];
int dfsc, dfn[N], low[N], dccCnt, root;
int bel[N], eb[M], fa[N << ][Lg], dep[N << ], id[N];
bool cut[N], vis[N << ];
vector <int> dcc[N]; struct Edge {
int to, nxt, id;
} e[M << ]; inline void add(int type, int from, int to, int eid) {
e[++tot].to = to;
e[tot].id = eid;
e[tot].nxt = head[type][from];
head[type][from] = tot;
} inline void read(int &X) {
X = ;
char ch = ;
int op = ;
for(; ch > ''|| ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} inline int min(int x, int y) {
return x > y ? y : x;
} void tarjan(int x) {
dfn[x] = low[x] = ++dfsc;
sta[++top] = x;
if(x == root && head[][x] == ) {
dcc[++dccCnt].push_back(x);
return;
} int son = ;
for(int i = head[][x]; i; i = e[i].nxt) {
int y = e[i].to;
if(!dfn[y]) {
tarjan(y);
low[x] = min(low[x], low[y]);
if(dfn[x] <= low[y]) {
++son;
if(x != root || son > ) cut[x] = ;
++dccCnt;
for(int z; ; ) {
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] = , fa[x][] = fat, dep[x] = depth;
for(int i = ; i <= ; i++)
fa[x][i] = fa[fa[x][i - ]][i - ];
for(int i = head[][x]; i; i = e[i].nxt) {
int y = e[i].to;
if(vis[y]) continue;
dfs(y, x, depth + );
}
} inline void swap(int &x, int &y) {
int t = x;
x = y;
y = t;
} inline int getLca(int x, int y) {
if(dep[x] < dep[y]) swap(x, y);
for(int i = ; i >= ; i--)
if(dep[fa[x][i]] >= dep[y])
x = fa[x][i];
if(x == y) return x;
for(int i = ; i >= ; i--)
if(fa[x][i] != fa[y][i])
x = fa[x][i], y = fa[y][i];
return fa[x][];
} int main() {
for(; ; ) {
read(n), read(m);
if(n == && m == ) break;
tot = ;
memset(head, , sizeof(head));
for(int x, y, i = ; i <= m; i++) {
read(x), read(y);
add(, x, y, i), add(, y, x, i);
} dfsc = dccCnt = top = ;
memset(dfn, , sizeof(dfn));
memset(low, , sizeof(low));
memset(cut, , sizeof(cut));
for(int i = ; i <= n; i++) dcc[i].clear(); for(int i = ; i <= n; i++)
if(!dfn[i]) tarjan(root = i); int now = dccCnt;
for(int i = ; i <= n; i++)
if(cut[i]) id[i] = ++now; /* printf("\n");
for(int i = 1; i <= dccCnt; i++, printf("\n")) {
for(unsigned int j = 0; j < dcc[i].size(); j++)
printf("%d ", dcc[i][j]);
}
printf("\n"); */ for(int i = ; i <= dccCnt; i++) {
for(unsigned int j = ; j < dcc[i].size(); j++) {
int x = dcc[i][j];
if(cut[x]) add(, id[x], i, ), add(, i, id[x], );
bel[x] = i;
} for(unsigned int j = ; j < dcc[i].size(); j++) {
int x = dcc[i][j];
for(int k = head[][x]; k; k = e[k].nxt) {
int y = e[k].to;
if(bel[y] == i) eb[e[k].id] = i;
}
}
} /* for(int i = 1; i <= n; i++)
printf("%d ", bel[i]);
printf("\n"); for(int i = 1; i <= m; i++)
printf("%d ", eb[i]);
printf("\n"); */ memset(dep, , sizeof(dep));
memset(fa, , sizeof(fa));
memset(vis, , sizeof(vis));
for(int i = ; i <= now; i++)
if(!vis[i]) dfs(i, , ); read(qn);
for(int x, y; qn--; ) {
read(x), read(y);
x = eb[x], y = eb[y];
if(x == y) puts("");
else printf("%d\n", (dep[x] + dep[y] - * dep[getLca(x, y)]) / );
}
}
return ;
}
lyd给的std好难看
HDU3686 Traffic Real Time Query的更多相关文章
- CH#24C 逃不掉的路 和 HDU3686 Traffic Real Time Query System
逃不掉的路 CH Round #24 - 三体杯 Round #1 题目描述 现代社会,路是必不可少的.任意两个城镇都有路相连,而且往往不止一条.但有些路连年被各种XXOO,走着很不爽.按理说条条大路 ...
- 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 ...
- 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 ...
- UVALive-4839 HDU-3686 Traffic Real Time Query System 题解
题目大意: 有一张无向连通图,问从一条边走到另一条边必定要经过的点有几个. 思路: 先用tarjan将双连通分量都并起来,剩下的再将割点独立出来,建成一棵树,之后记录每个点到根有几个割点,再用RMQ求 ...
- 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 ...
- Traffic Real Time Query System 圆方树+LCA
题目描述 City C is really a nightmare of all drivers for its traffic jams. To solve the traffic problem, ...
- HDU Traffic Real Time Query System
题目大意是:对于(n, m)的图,给定边a, b查询从a到b要经过的割点的最少数目. 先tarjan算法求双连通然后缩点,即对于每个割点将周围的每个双连通看成一个点与之相连.然后求解LCA即可,距离d ...
随机推荐
- PHP数据结构之实现栈
接着前面PHP数据结构来学习,今天写的是实现栈. <?php class stack //定义一个栈的类 { private $size; //栈的空间大小 private $top; // 栈 ...
- poj1321
这个题要是乍一看很难会想深搜,确实如此,可如果知道了深搜的方法,这个题就简 了不少,至于用深搜的时候要考虑当k==n和k<n时这咱种情况,当K==n时,当然很好想 到深搜搜下很容易找到所有方法, ...
- yum search/intall, Error: xz compression not available
转自:http://blog.hexu.org/archives/2060.shtml 遇到这个问题情景: 下午第一台系统是Centos7, 安装配置完成后,接着一台是Centos 6 系统,由于疏忽 ...
- P1605 迷宫(洛谷)
题目背景 迷宫 [问题描述] 给定一个N*M方格的迷宫,迷宫里有T处障碍,障碍处不可通过.给定起点坐标和终点坐标,问: 每个方格最多经过1次,有多少种从起点坐标到终点坐标的方案.在迷宫中移动有上下左右 ...
- Oracle 存储过程_(收集)
oracle 存储过程的基本语法 1.基本结构 CREATE OR REPLACE PROCEDURE 存储过程名字( 参数1 IN NUMBER, 参数2 IN NUMBER) IS变量 ...
- AfxExtractSubString 函数的相关问题
AfxExtractSubString函数的用法 注:本文系rainy8758原创,转载请注明出处:http://blog.hjenglish.com/rainy8758/articles/10109 ...
- AFN 请求数据https
第一步: 导入afn库 第二步: 在pch中添加 #import <SystemConfiguration/SystemConfiguration.h> #import <Mobil ...
- Day2-VIM(六): 恢复
恢复在VIM里比较简单,不过想要具体恢复到某个时间段很难 就我的经验而言,有时候使用恢复还不如删了重写 这里我们来讲讲恢复.撤销和重复命令的使用 u 撤消上次命令 U 恢复整行 ctrl+r 重做 . ...
- 浅谈Java中的对象和对象引用
浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...
- Zookeeper学习(八):Zookeeper的数据发布与订阅模式
http://blog.csdn.net/ZuoAnYinXiang/article/category/6104448 1.发布订阅的基本概念 1.发布订阅模式可以看成一对多的关系:多 ...