自用板子
```
//最近公共祖先(LCA)//
struct Edge { int to, next; }edge[2 * N]; //链式前向星
int head[2 * N], cnt;
void init() //链式前向星:初始化
{
for (int i = 0; i < 2 * N; ++i) { edge[i].next = -1; head[i] = -1; }
cnt = 0;
}
void addedge(int u, int v) //链式前向星:加边
{
edge[cnt].to = v; edge[cnt].next = head[u]; head[u] = cnt++;
}
//以上是链式前向星
int fa[N][20], deep[N];
void dfs(int x, int father) //求x的深度deep[x]和fa[x][]。father是x的父结点。
{
deep[x] = deep[father] + 1; //深度:比父结点深度多1
fa[x][0] = father; //记录父结点
for (int i = 1; (1 << i) <= deep[x]; i++) //求fa[][]数组,它最多到根结点
fa[x][i] = fa[fa[x][i - 1]][i - 1];
for (int i = head[x]; ~i; i = edge[i].next) //遍历结点i的所有孩子。~i可写为i!=-1
if (edge[i].to != father) //邻居:除了父亲,都是孩子
dfs(edge[i].to, x);
}
int LCA(int x, int y)
{
if (deep[x] < deep[y]) swap(x, y); //让x位于更底层,即x的深度值更大
//(1)把x和y提到相同的深度
for (int i = 19; i >= 0; i--) //x最多跳19次:2^19 > 500005
if (deep[x] - (1 << i) >= deep[y]) //如果x跳过头了就换个小的i重跳
x = fa[x][i]; //如果x还没跳到y的层,就更新x继续跳
if (x == y) return x; //y就是x的祖先
//(2)x和y同步往上跳,找到LCA
for (int i = 19; i >= 0; i--) //如果祖先相等,说明跳过头了,换个小的i重跳
if (fa[x][i] != fa[y][i]) //如果祖先不等,就更新x、y继续跳
{
x = fa[x][i]; y = fa[y][i];
}
return fa[x][0]; //最后x位于LCA的下一层,父结点fa[x][0]就是LCA
}
int main()
{
init(); //初始化链式前向星
int n, m, root; scanf("%d%d%d", &n, &m, &root);
for (int i = 1; i < n; i++) //读一棵树,用链式前向星存储
{
int u, v; scanf("%d%d", &u, &v);
addedge(u, v); addedge(v, u);
}
dfs(root, 0); //计算每个结点的深度并预处理fa[][]数组
while (m--)
{
int a, b; scanf("%d%d", &a, &b);
printf("%d\n", LCA(a, b));
}
return 0;
}
```