刚打完LCA板子,写个东西记下
- 树剖的LCA比倍增的快很多,代码又不长,还比较容易理解,当然树剖啦
- 具体的什么轻链重链就不多赘述
- 算法流程:
- dfs第一遍求出 结点i的深度, 以i为根的子树大小, 结点i的父亲, 并求出重链
- dfs第二遍求出 结点i所在重链的链顶(如果在重链上)
- 开始LCA,两个点往上找,深度大的点就往上跳,这个点如果在重链上,就跳到所在重链的链顶的父亲处,在轻链上,就直接跳到自己父亲上
代码:(洛谷LCA板子题)
#include <bits/stdc++.h>
#define SIZE 500000
using namespace std;
int n, m, root, x, y, len;
int f[SIZE + 30], dep[SIZE + 30], siz[SIZE + 30], son[SIZE + 30], top[SIZE + 30], fa[SIZE + 30];
struct Edge {
int s, next;
}e[SIZE * 4 + 30];
inline void AddEdge(int u,int v){
e[++len]=(Edge){v, f[u]};
f[u] = len;
}
inline void dfs1(int s) {//预处理dep, siz, fa, son
siz[s] = 1;
for (int i = f[s]; i; i = e[i].next) {
int d = e[i].s;
if (fa[s] != d) {
fa[d] = s;
dep[d] = dep[s] + 1;
dfs1(d);
siz[s] += siz[d];
if (siz[son[s]] < siz[d])
son[s] = d;
}
}
}
inline void dfs2(int s) {//预处理top
if (s == son[fa[s]])
top[s] = top[fa[s]];
else top[s] = s;
for (int i = f[s]; i; i = e[i].next)
if (e[i].s != fa[s])
dfs2(e[i].s);
}
int LCA(int a, int b) {
while (top[a] != top[b]) {
if(dep[top[a]] < dep[top[b]]) a = fa[top[a]];
else b = fa[top[b]];
}
if (dep[a] >= dep[b]) return b;
else return a;
}
int main() {
scanf ("%d%d%d", &n, &m, &root);
for (int i = 1; i < n; ++i) {
scanf ("%d%d", &x, &y);
AddEdge(x, y); AddEdge(y, x);
}
dep[root] = 1;
dfs1(root);
dfs2(root);
for (int i = 1; i <= m; ++i) {
scanf ("%d%d", &x, &y);
printf("%d\n", LCA(x, y));
}
return 0;
}