在dfs序列上维护RMQ求LCA
作者:
烟台陈坤
,
2024-07-18 09:41:02
,
所有人可见
,
阅读 11
#include <bits/stdc++.h>
#define MAXP 20
using namespace std;
const int N = 5e5 + 10;
int n, m, q;
bool flag[N + 10];
vector<int> e[N + 10], v[N + 10];//v是这条边的权值
// dis[i]:从根到节点 i 的距离
long long dis[N + 10];
// 在 dfs 序列上维护 rmq 求 lca
int clk, bgn[N + 10];
int lg[N * 2 + 10], f[MAXP][N * 2 + 10];
void dfs(int sn, int fa)
{
f[0][++clk] = sn;
bgn[sn] = clk;
for (int i = 0; i < e[sn].size(); i++)
{
int fn = e[sn][i];
if (fn == fa) continue;
dis[fn] = dis[sn] + v[sn][i];
dfs(fn, sn);
f[0][++clk] = sn;
}
}
// rmq 预处理
void preLca()
{
lg[1] = 0;
for (int i = 2; i <= N * 2; i++) lg[i] = lg[i >> 1] + 1;
for (int p = 1; p < MAXP; p++)
for (int i = 1; i + (1 << p) - 1 <= clk; i++)
{
int j = i + (1 << (p - 1));
if (dis[f[p - 1][i]] < dis[f[p - 1][j]]) f[p][i] = f[p - 1][i];
else f[p][i] = f[p - 1][j];
}
}
// 求节点 x 和 y 的 lca
int lca(int x, int y)
{
if (bgn[x] > bgn[y]) swap(x, y);
int p = lg[bgn[y] - bgn[x] + 1];
int a = f[p][bgn[x]], b = f[p][bgn[y] - (1 << p) + 1];
if (dis[a] < dis[b]) return a;
else return b;
}
void solves()
{
cin >> n >> m >> q;
for (int i = 1; i <= n; i++) e[i].clear(), v[i].clear();
for (int i = 1; i < n; i++)
{
int x, y, z;
cin >> x >> y;
z = 1;//这里权值可以任意修改
e[x].push_back(y); v[x].push_back(z);
e[y].push_back(x); v[y].push_back(z);
}
clk = 0; //每组数据要清空
dfs(q, 0);
preLca();
while (m--)
{
int a, b;
cin >> a >> b;
cout << lca(a, b) << endl;
}
}
int main()
{
int t = 1;
//cin >> t;
while (t--)
solves();
return 0;
}