【模板】最近公共祖先(LCA)

https://www.luogu.org/problem/P3379

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#define mem(jlsb) memset(jlsb,-1,sizeof(jlsb));
using namespace std;

const int MAXN=2000000;
int n,m,ss,head[MAXN],next[MAXN],to[MAXN],x,y,ec;
int p[MAXN][30],deep[MAXN];

inline int read(){
   int s = 0, ww = 1; char ch = getchar();
   while(ch < '0' || ch > '9'){ if(ch == '-') ww = -1; ch = getchar(); }
   while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
   return s*ww;
}

void add(int mu, int mv){	 
	to[++ec]=mv;
	next[ec]=head[mu];
	head[mu]=ec;
}

void clen(){
	mem(head);mem(next);
}

void dfs(int u){
	for(int jl=head[u];jl!=-1;jl=next[jl])
		if (!deep[to[jl]]){			
			deep[to[jl]] = deep[u]+1;
			p[to[jl]][0] = u; 
			dfs(to[jl]);
		}
}

void init(){
	for(int j=1;(1<<j)<=n;j++)
		for(int i=1;i<=n;i++)
			if(p[i][j-1]!=-1)
				p[i][j]=p[p[i][j-1]][j-1];
}

int lca(int aa,int bb){
	if(deep[aa]<deep[bb])swap(aa,bb);
	int jl=0;
	while((1<<jl)<=deep[aa]) jl++;
	jl--;
	for(int j=jl;j>=0;j--)
		if(deep[aa]-(1<<j)>=deep[bb])
			aa=p[aa][j];
	if(aa==bb)return aa;
	for(int j=jl;j>=0;j--){
		if(p[aa][j]!=-1&&p[aa][j]!=p[bb][j]){
			aa=p[aa][j];
			bb=p[bb][j];
		}
	}
	return p[aa][0];
}

int main(){
	clen();
	n=read();m=read();ss=read();
	for(int i=1;i<n;i++){
		x=read();y=read();
		add(x,y);add(y,x);
	}
	deep[ss]=1;dfs(ss);init();
	while(m--){
		int s,t;s=read();t=read();
		printf("%d\n",lca(s,t));
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值