题目
emmm求树上两点的lca
luogu P3379 【模板】最近公共祖先(LCA)
题解
- 树链剖分的讲解
- 树剖的思路:
- 对于在同一条链上的两个点,深度小的即为lca
- 对于不在同一条链上的两个点,可以把它们跳到同一深度,同理即可
c o d e code code
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <deque>
#include <stack>
#include <queue>
#include <cstdio>
#include <cctype>
#include <vector>
#include <string>
#include <cstring>
#include <iomanip>
#include <complex>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long LL;
const int maxn = 500000 + 1000;
template <class T>
inline void read(T &s) {
s = 0;
T w = 1, ch = getchar();
while (!isdigit(ch)) { if (ch == '-') w = -1; ch = getchar(); }
while (isdigit(ch)) { s = (s << 1) + (s << 3) + (ch ^ 48); ch = getchar(); }
s *= w;
}
int n, m, s, tot;
int lin[maxn], son[maxn], dep[maxn], siz[maxn];
int top[maxn], fat[maxn];
struct node { int next, to; } edge[maxn << 1];
inline void add(int from, int to) {
edge[++tot].to = to;
edge[tot].next = lin[from];
lin[from] = tot;
}
void dfs1(int u, int fa, int depth) {
siz[u] = 1;
fat[u] = fa;
dep[u] = depth;
int maxson = -1;
for (int i = lin[u]; i; i = edge[i].next) {
int v = edge[i].to;
if (v == fa) continue;
dfs1(v, u, depth + 1);
siz[u] += siz[v];
if (siz[v] > maxson) {
maxson = siz[v];
son[u] = v;
}
}
}
void dfs2(int u, int tp) {
top[u] = tp;
if (!son[u]) return ;
dfs2(son[u], tp);
for (int i = lin[u]; i; i = edge[i].next) {
int v = edge[i].to;
if (v == fat[u] || v == son[u]) continue;
dfs2(v, v);
}
}
int get_lca(int x, int y) {
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
x = fat[top[x]];
}
// printf("-- %d %d --\n", x, y);
return dep[x] > dep[y] ? y : x;
}
int main() {
read(n), read(m), read(s);
for (int i = 1; i < n; ++i) {
int u, v;
read(u), read(v);
add(u, v);
add(v, u);
}
dfs1(s, 0, 1);
dfs2(s, s);
while (m--) {
int x, y;
read(x), read(y);
printf("%d\n", get_lca(x, y));
}
return 0;
}