LCA板子

倍增法求LCA

编码比较容易

#define _CRT_SECURE_NO_WARNINGS 
#include<iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<sstream>
#include<string>
#include<string.h>
#include<iomanip>
#include<stdlib.h>
#include<map>
#include<queue>
#include<limits.h>
#include<climits>
#include<fstream>
#include<stack>
#define IOS ios::sync_with_stdio(false), cin.tie(0) ,cout.tie(0)
using namespace std;
#define int long long
//LCA板子
const int N = 5e5 + 5;
struct Edge { int to, next; }edge[2*N];
int head[2 * N], cnt;//链式前向星
void init()
{
	cnt = 0;
	for (int i = 0; i < 2 * N; i++) { edge[i].next = -1, head[i] = -1; }
}
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;
	fa[x][0] = father;
	for (int i = 1; (1 << i) <= deep[x]; i++)
		fa[x][i] = fa[fa[x][i - 1]][i - 1];
	for (int i = head[x]; i != -1; i = edge[i].next)
		if (edge[i].to != father)
			dfs(edge[i].to, x);
}
int LCA(int x, int y)
{
	if (deep[x] < deep[y])swap(x, y);
	for (int i = 19; i >= 0; i--)
		if (deep[x] - (1 << i) >= deep[y])
			x = fa[x][i];
	if (x == y)return x;
	for (int i = 19; i >= 0; i--)// 如果祖先相等,说明可能跳过头了
		if (fa[x][i] != fa[y][i])//如果不相等,那两个都往前跳
			x = fa[x][i], y = fa[y][i];
	return fa[x][0];
}
signed main()
{
	IOS;
	init();
	int n, m, root; cin >> n >> m >> root;
	for (int i = 1; i < n; i++)
	{
		int u, v; cin >> u >> v;
		addedge(u, v), addedge(v, u);
	}
	dfs(root, 0);
	while (m--)
	{
		int a, b; cin >> a >> b;
		cout << LCA(a, b) << '\n';
	}

	return 0;
}

posted on 2024-07-20 19:51  WHUStar  阅读(1)  评论(0编辑  收藏  举报