【luogu4320】道路相遇 (圆方树 + LCA)
Description
给你一张\(~n~\)个点\(~m~\)条边的无向图,保证无重边无自环, 共\(~q~\)组询问求\(~x~\)到\(~y~\)的路径上必经的点数。
Solution
建出圆方树后, 不难发现答案所求就是\(~x~\)到\(~y~\)的路径上的圆点个数, 而圆方树拥有的优秀性质就是相邻点对一圆一方,所以圆点个数就是 树上路径长度的\(~1/2~ + 1~\), 树上路径长度可以简单地由\(~dep_x,~dep_y, ~dep_{lca(x, ~y)}~\)求得。
Code
#include<bits/stdc++.h>
#define Set(a, b) memset(a, b, sizeof (a))
#define For(i, j, k) for(int i = j; i <= k; ++i)
#define Forr(i, j, k) for(int i = j; i >= k; --i)
#define Travel(i, u, G) for(int i = G.beg[u], v = G.to[i]; i; i = G.nex[i], v = G.to[i])
using namespace std;
inline int read() {
int x = 0, p = 1; char c = getchar();
for(; !isdigit(c); c = getchar()) if(c == '-') p = -1;
for(; isdigit(c); c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
return x *= p;
}
template<typename T> inline bool chkmin(T &a, T b) { return a > b ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
inline void File() {
#ifndef ONLINE_JUDGE
freopen("P4320.in", "r", stdin);
freopen("P4320.out", "w", stdout);
#endif
}
const int N = 1e6 + 10, M = N << 1;
struct edge {
int e = 1, beg[N], nex[M], to[M];
inline void add(int x, int y) { to[++ e] = y, nex[e] = beg[x], beg[x] = e; }
} G1, G2;
int n, m, u, v, dfn[N], low[N];
int cnt, clk, F[21][N], dep[N];
stack<int> S;
inline void tarjan(int u, int f) {
dfn[u] = low[u] = ++ clk, S.push(u);
Travel(i, u, G1) if (v != f) {
if (!dfn[v]) {
tarjan(v, u), chkmin(low[u], low[v]);
if (low[v] >= dfn[u]) {
F[0][++ cnt] = u, G2.add(u, cnt);
while (!S.empty()) {
int x = S.top(); S.pop();
F[0][x] = cnt, G2.add(cnt, x);
if (x == v) break;
}
}
} else chkmin(low[u], dfn[v]);
}
}
inline void dfs(int u, int las) {
Travel(i, u, G2) dep[v] = dep[u] + 1, dfs(v, u);
}
inline int lca(int x, int y) {
if (dep[x] < dep[y]) swap(x, y);
Forr(i, 20, 0) if (dep[F[i][x]] >= dep[y]) x = F[i][x];
if (x == y) return y;
Forr(i, 20, 0) if (F[i][x] ^ F[i][y]) x = F[i][x], y = F[i][y];
return F[0][x];
}
int main() {
File();
cnt = n = read(), m = read();
For(i, 1, m) u = read(), v = read(), G1.add(u, v), G1.add(v, u);
For(i, 1, n) if (!dfn[i]) tarjan(i, 0);
dfs(1, 0);
For(j, 1, 20) For(i, 1, n) F[j][i] = F[j - 1][F[j - 1][i]];
for (int Case = read(); Case --;) {
u = read(), v = read();
int ans = (dep[u] + dep[v] - (dep[lca(u, v)] << 1)) / 2 + 1;
printf("%d\n", ans);
}
return 0;
}
【luogu4320】道路相遇 (圆方树 + LCA)的更多相关文章
- luoguP4320 道路相遇 圆方树
标题已经告诉你怎么做了..... 两点间的圆点个数即为所求 建出圆方树后打个树剖求$lca$就行..... 复杂度$O(n + q \log n)$ #include <cstdio> # ...
- P4320-道路相遇,P5058-[ZJOI2004]嗅探器【圆方树,LCA】
两题差不多就一起写了 P4320-道路相遇 题目链接:https://www.luogu.com.cn/problem/P4320 题目大意 \(n\)个点\(m\)条边的一张图,\(q\)次询问两个 ...
- Traffic Real Time Query System 圆方树+LCA
题目描述 City C is really a nightmare of all drivers for its traffic jams. To solve the traffic problem, ...
- 【洛谷 P4320】 道路相遇 (圆方树,LCA)
题目链接 题意:给一张无向图和\(M\)个询问,问\(u,v\)之间的路径的必经之点的个数. 对图建出圆方树,然后必经之点就是两点路径经过的原点个数,用\((dep[u]+dep[v]-dep[LCA ...
- 图论杂项细节梳理&模板(虚树,圆方树,仙人掌,欧拉路径,还有。。。)
orzYCB 虚树 %自为风月马前卒巨佬% 用于优化一类树形DP问题. 当状态转移只和树中的某些关键点有关的时候,我们把这些点和它们两两之间的LCA弄出来,以点的祖孙关系连成一棵新的树,这就是虚树. ...
- 仙人掌&圆方树
仙人掌&圆方树 Tags:图论 [x] [luogu4320]道路相遇 https://www.luogu.org/problemnew/show/P4320 [ ] [SDOI2018]战略 ...
- [SDOI2018]战略游戏 圆方树,树链剖分
[SDOI2018]战略游戏 这题是道路相遇(题解)的升级版,询问的两个点变成了\(S\)个点. LG传送门 还是先建出圆方树,考虑对于询问的\(S\)个点,答案就是圆方树上能包含这些点的最小连通块中 ...
- Note -「圆方树」学习笔记
目录 圆方树的定义 圆方树的构造 实现 细节 圆方树的运用 「BZOJ 3331」压力 「洛谷 P4320」道路相遇 「APIO 2018」「洛谷 P4630」铁人两项 「CF 487E」Touris ...
- BZOJ5329:[SDOI2018]战略游戏(圆方树,虚树)
Description 省选临近,放飞自我的小Q无心刷题,于是怂恿小C和他一起颓废,玩起了一款战略游戏. 这款战略游戏的地图由n个城市以及m条连接这些城市的双向道路构成,并且从任意一个城市出发总能沿着 ...
随机推荐
- ajax上传文件以及实现上传进度条(转载)
做微信企业号的时候,在‘我的日志'功能模块里边需要添加一个上传文件的功能,并且要显示上传过程中的进度条和提交后的文件名列表,于是做了基于ajax的文件上传,UI用的是MUI框架,后台是TP框架 前端代 ...
- Luogu2046 NOI2010 海拔 平面图、最小割、最短路
传送门 首先一个不知道怎么证的结论:任意点的\(H\)只会是\(0\)或\(1\) 那么可以发现原题的本质就是一个最小割,左上角为\(S\),右下角为\(T\),被割开的两个部分就是\(H=0\)与\ ...
- Luogu3067 平衡的奶牛群 Meet in the middle
题意:给出$N$个范围在$[1,10^8]$内的整数,问有多少种取数方案使得取出来的数能够分成两个和相等的集合.$N \leq 20$ 发现爆搜是$O(3^N)$的,所以考虑双向搜索. 先把前$3^\ ...
- odoo 11 实现多个字段对应一个查询参数的查询
在整理英语单词开发模块的过程中,有这样一个需求,就是我在查询界面里输入一个查询的值A,这个A可能是下面的任何一个值 1.一个英语单词 2.汉语文字 3.一个英语单词的部分 这里有两张表:engli ...
- 安卓自动化测试,贺晓聪之uiautomator设备和选择器~Python详解
1.设备对象 引入uiautomator,获取设备对象<所谓设备对象可理解为:Android模拟器或者真机> 语法:from uiautomator import device as d ...
- 生成32位UUID及生成指定个数的UUID
参考地址:https://blog.csdn.net/xinghuo0007/article/details/72868799 UUID是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯 ...
- 从源码的角度看 React JS 中批量更新 State 的策略(上)
在之前的文章「深入理解 React JS 中的 setState」与 「从源码的角度再看 React JS 中的 setState」 中,我们分别看到了 React JS 中 setState 的异步 ...
- DRBD详细解说及配置过程记录
一.DRBD介绍 DRBD(Distributed ReplicatedBlock Device)是一种基于软件的,无共享,分布式块设备复制的存储解决方案,在服务器之间的对块设备(硬盘,分区,逻辑卷等 ...
- 作用域&作用域链和with,catch语句&闭包
作用域(函数) 作用域:变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期; 在一些类C编程语言中花括号内的每一段代码都有各自的作用域,而且变量在声明它们的代码段外是不可见的,称之为块 ...
- Daily Scrumming* 2015.12.19(Day 11)
一.团队scrum meeting照片 二.成员工作总结 姓名 任务ID 迁入记录 江昊 任务1090 https://github.com/buaaclubs-team/temp-front/com ...