代码模版
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
const int N = 101000;
const int mod = 1e2 + 7;
int e[N], ne[N], h[N];
int idx = 0;
int depth[N], fa[N][20];
int root;
void add(int a, int b)
{
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
void bfs()//预处理
{
deque<int> q;
memset(depth,0x3f,sizeof(depth));
depth[0] =0;//哨兵
depth[root] = 1;
q.push_back(root);
while(q.size())
{
int i= q.front();
q.pop_front();
for(int t =h[i];t!=-1;t = ne[t])
{
int j =e[t];
if(depth[j]<depth[i]) continue;
fa[j][0] =i;
depth[j] =depth[i]+1;
for(int k = 1;k<=15;k++)
{
fa[j][k] =fa[fa[j][k-1]][k-1];
}
q.push_back(j);
}
}
}
int LCA(int a, int b)
{
if (depth[a] < depth[b])
swap(a, b);
for (int i = 15; i >= 0; i--)
{
if (depth[fa[a][i]] >= depth[b])
{
a = fa[a][i];
}
}
if (a == b) return a;
for (int i = 15; i >= 0; i--)
{
if (fa[a][i] != fa[b][i])
{
a = fa[a][i];
b = fa[b][i];
}
}
return fa[a][0];
}
int main()
{
int n;
cin >> n;
memset(h, -1, sizeof(h));
while (n--)
{
int a, b;
cin >> a >> b;
if (b == -1)
{
root = a;
continue;
}
add(a, b);
add(b, a);
}
bfs();
int q;
cin >> q;
while (q--)
{
int a, b;
cin >> a >> b;
int pp = LCA(a, b);
//pp就是最近公共祖先
}
注意事项
- 注意对于哨兵的初始化
- 当遍历子节点是时,注意跳过父节点
- bfs的关键点在于倍增代码,记得先初始化fa[j][0] = i;
- LCA函数代码一开始要先确定那个点更深,判断完之后,让两个点到同一深度
- LCA代码中,for循环是15到0,从大到小,bfs是从小到大
- 重点:LCA函数最后返回的是fa[a][0],如果返回的fa[a][0]是0的话,说明没有公共祖先