LCA

LCA

LCA ver1
int LCA(int u, int v) {
	if (D[u] < D[v])swap(u, v);//保证D[u]>D[v]
	//2^L 是不小与树的高度的最小的2的幂,其中L=ceil(log2(n));
	for (int h = L; h >= 0; h--)//让u倍增往上爬,对于D(u)-D(v)的二进制中所以的2^h,执行u=UP[u][h]
		if (D[UP[u][h]] >= D[v])
			u = UP[u][h];
	if (u == v)return u;//向上爬之后D(u)=D(v)
	for (int h = L; h >= 0; h--)//让u,v同时往上爬,最后到达最近公共祖先
		if (UP[u][h] != UP[v][h])
			u = UP[u][h], v = UP[v][h];
	return UP[u][0];
}

//ver2
using namespace std;
const int maxn = 5e5 + 10;
const int len = 33;
int Tin[maxn], Tout[maxn], timer;
int UP[maxn][len];
int L = 20;
int D[maxn];
vector<int> G[maxn];
//LCA预处理
void dfs(int u, int fa) {

	UP[u][0] = fa;	D[u] = D[fa] + 1;
	Tin[u] = ++timer;
	for (int i = 1; (1 << i) <= D[u]; i++)
		UP[u][i] = UP[UP[u][i - 1]][i - 1];
	for (auto v : G[u]) {
		if (v == fa)continue;
		dfs(v, u);
	}
	Tout[u] = timer;
}
bool isAncestor(int u, int v) { return Tin[u] <= Tin[v] && Tout[u] >= Tout[v]; }


int LCA(int u, int v) {
	if (D[u] > D[v])return LCA(v, u);//保证D(u)<=D(v)
	if (isAncestor(v, u))return v;
	if (isAncestor(u, v))return u;//如果u是v的祖先,直接返回u即可。
	//否则UP(u,i)不是v的祖先,就沿着u往上爬2^i级,直到爬到LCA(u,v)子节点为止。
	for (int i = ceil(log2(D[u])); i >= 0; --i)
		if (UP[u][i] && !isAncestor(UP[u][i], v))//有零的影响
			u = UP[u][i];
	return UP[u][0];
}


int n, m, rt;

int main()
{

	ios::sync_with_stdio(false);
	cin >> n >> m >> rt;
	for (int i = 1; i < n; i++)
	{
		int a, b; cin >> a >> b;
		G[a].push_back(b);
		G[b].push_back(a);
	}
	dfs(rt, rt);
	while (m--)
	{
		int a, b;
		cin >> a >> b;
		cout << LCA(a, b) << endl;
	}
	return 0;
}

本文作者:可可爱爱奇奇怪怪。。。

本文链接:https://www.cnblogs.com/ccsuf/p/15370085.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @ 2021-10-05 23:58  warmhearthhh  阅读(103)  评论(0编辑  收藏  举报
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.