题目链接:https://www.luogu.org/problemnew/show/P3379
注释:表示节点 的 级祖先,,表示节点 的深度,,表示 的值(用来优化常数)。
这篇博客讲的非常详细:https://www.luogu.com.cn/blog/morslin/solution-p3379
PS:vector存图可能会超时。
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 7;
int fa[N][20], deep[N], lg[N], head[N];
int n, m, s, cnt;
struct Edge
{
int to, next;
}edge[N << 1];
void init()
{
memset(head, -1, sizeof head);
cnt = 0;
}
void add_edge(int u, int v)
{
edge[cnt].to = v;
edge[cnt].next = head[u];
head[u] = cnt++;
}
void dfs(int rt, int fath)
{
deep[rt] = deep[fath] + 1;
fa[rt][0] = fath;
for(int i = 1; (1 << i) <= deep[rt]; i++)
fa[rt][i] = fa[fa[rt][i-1]][i-1];
for (int i = head[rt]; i != -1; i = edge[i].next)
if(edge[i].to != fath) dfs(edge[i].to, rt);
}
int lca(int x, int y)
{
if(deep[y] > deep[x])
swap(x, y);
while(deep[x] > deep[y])
x = fa[x][lg[deep[x]-deep[y]]];
if(x == y) return x;
for(int i = lg[deep[x]]; i >= 0; i--)
{
if(fa[x][i] != fa[y][i])
x = fa[x][i], y = fa[y][i];
}
return fa[x][0];
}
int main()
{
scanf("%d%d%d",&n,&m,&s);
init();
for(int i = 1; i < n; i++)
{
int u, v;
scanf("%d%d",&u,&v);
add_edge(u, v);
add_edge(v, u);
}
lg[0] = -1;
for(int i = 1; i <= n; i++)
lg[i] = lg[i >> 1] + 1;
dfs(s, 0);
while(m--)
{
int x, y;
scanf("%d%d",&x,&y);
printf("%d\n",lca(x,y));
}
return 0;
}