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 ...
随机推荐
- 常用集合ArrayList浅度解析
首先,先看一下java中对ArrayList的定义代码: public class ArrayList<E> extends AbstractList<E> implement ...
- 魔法效果——dijkstra+堆(邻接表存储)
dijkstra本身每次要for一遍,才能找出最小的节点,但用了堆之后,直接取出堆首就可以了. 但要注意的一点是,c++自带的stl里的priority_queue本身是先入大出的,而我们要求的是最小 ...
- SQL使用指南(2)—— 约束的使用
主键约束 (1)创建表时添加主键约束 primary key<column_name> (2) 修改表时添加主键约束 ALTER TABLE table_name ADD CONSTRAI ...
- UVA - 11768 Lattice Point or Not (扩展欧几里得)
求一条线段上有多少个整点. 是道扩欧基础题,列出两点式方程,然后分四种情况讨论即可.但细节处理较多很容易写挫(某zzWA了十几发才过掉的). 由于数据精度较小,浮点数比较没有用eps,直接==比较了. ...
- java-04类和对象课堂练习
1.请运行并输入以下代码,得到什么结果 public class Test { public static void main(String[] args){ Foo obj1=new Foo(); ...
- mendeley 参考文献管理工具
本文由Suzzz原创,发布于http://www.cnblogs.com/Suzzz/p/4044144.html,转载请保留此声明 目录 介绍 功能 运行截图 安装方法 创建 Desktop Ent ...
- 用Python+Django1.9在Eclipse环境下开发web网站
最近想学习一下python django, 按网上各位大神们的说明,试着做了一下,这里记录下来,做个笔记. 参考 http://www.cnblogs.com/linjiqin/p/3595891.h ...
- C# 常用文件操作
public class IoHelper { /// <summary> /// 判断文件是否存在 /// </summary> /// <param name=&qu ...
- Excel开发学习笔记:界面交互与控件的布局
遇到一个数据处理自动化的问题,于是打算开发一个基于excel的小工具.在业余时间一边自学一边实践,抽空把一些知识写下来以备今后参考,因为走的是盲人摸象的野路子,幼稚与错误请多包涵. , ).value ...
- UE4模型导入基础教程
转自:http://www.unrealchina.net/portal.php?mod=view&aid=290