倍增 70PTS 求调 玄关
查看原帖
倍增 70PTS 求调 玄关
757432
laijingnian楼主2023/12/24 17:20
#include <iostream>
#include <cstring>

using namespace std;

typedef long long type;
const type N = 500010,M = N * 2;

type h[N],e[N],ne[N],idx;
type depth[N],fa[N][26]; // fa[i][j] 表示 i 向上跳 2 ^ j 步达到的节点
type q[N]; // bfs 宽搜队列

void add(type a,type b)
{
	e[idx] = b;
	ne[idx] = h[a];
	h[a] = idx;
	idx++;
}

void up(type &x,type high) // x 向上跳 high 高
{
	for(int i = 0;high;i++)
	{
		if(high & 1) x = fa[x][i];
		high >>= 1;
	}
}

void bfs(type root)
{
	memset(depth,0x3f,sizeof depth);
	depth[0] = 0,depth[root] = 1;
	type hh = 0,tt = 0;
	q[0] = root;
	while(hh <= tt)
	{
		auto t = q[hh++];
		for(auto i = h[t];~i;i = ne[i]) // ~i 等价于 i != -1;
		{
			auto j = e[i];
			if(depth[j] > depth[t] + 1)
			{
				depth[j] = depth[t] + 1; // 更新depth
				q[++tt] = j; // 放入队列
				fa[j][0] = t; // 更新fa[j][0]
				for(type k = 1;k <= 25;k++) // 更新fa[j][1...25]
					fa[j][k] = fa[fa[j][k-1]][k - 1];
			}
		}
	}
}

type lca(type a,type b)
{
	if(depth[a] < depth[b]) swap(a,b);
	type high = depth[a] - depth[b];
	up(a,high);
	if(a == b) return a;
	for(type k = 25;k >= 0;k--)
		if(fa[a][k] != fa[b][k])
		{
			a = fa[a][k];
			b = fa[b][k];
		}
	return fa[a][0];
}

int main()
{
	type n,m,root;
	memset(h,-1,sizeof h);
	cin >> n >> m >> root;
	for(int i = 0;i < n-1;i++)
	{
		type a,b;
		cin >> a >> b;
		add(a,b),add(b,a);
	}
	bfs(root);
	while(m--)
	{
		type a,b;
		cin >> a >> b;
		if(a == b) cout << a << "\n";
		else cout << lca(a,b) << "\n";
	}
	return 0;
}
2023/12/24 17:20
加载中...