模板——倍增LCA

n个节点,m个询问,root为根节点,fa[i][j]表示i的第2j个祖先

#include<bits/stdc++.h>
using namespace std;
const int P=30;
//vector son[500001];
//若清楚每条边哪个是父节点那个是子节点,可以用vector,son[i]表示以i为父节点的子节点;
int n,m,deep[500001],fa[500001][30]={0},root,jump[500005],num=0;
bool judge[500005]={0};
struct nob{
	int sta,ed,jump;
}a[1000005];
//邻接表存储边
void add(int sta,int ed){
	num++;
	a[num].sta=sta;
	a[num].ed=ed;
	a[num].jump=jump[sta];
	jump[sta]=num;
}
void dfs(int pos){
	judge[pos]=1;
	for (int i=jump[pos]; i>0; i=a[i].jump){
		if (judge[a[i].ed]) continue;
		deep[a[i].ed]=deep[pos]+1;
		fa[a[i].ed][0]=pos;
		dfs(a[i].ed);
	}
}
void beizeng(){
	for (int i=1; i<P; i++){
		for (int l=1; l<=n; l++){
			fa[l][i]=fa[fa[l][i-1]][i-1];
		}
	}
}
int LCA(int x,int y){
	if (deep[y]>deep[x])
	swap(x,y);
	int s=deep[x]-deep[y];
	for (int i=0; i<P; i++)
		if ((1<<i)&s)
			x=fa[x][i];
	//将深度转为二进制,用倍增来跳 
	if (x==y) return x;
	for (int i=P-1; i>=0; i--){
		if (fa[x][i]!=fa[y][i]){
			x=fa[x][i];
			y=fa[y][i];
		}
	}
	return fa[x][0];
}
int main(){
	scanf("%d%d%d",&n,&m,&root);
	//若没有说明根节点的话,那么fa[i][0]==0的为根节点 
	for (int i=1,x,y; i<n; i++){
		scanf("%d%d",&x,&y);
		add(x,y);
		add(y,x);
	}
	deep[root]=1;
	dfs(root);
	beizeng();
	for (int i=1,x,y; i<=m; i++){
		scanf("%d%d",&x,&y);
		printf("%d\n",LCA(x,y));
	}
	return 0;
}
posted @ 2017-10-22 20:42  |斗蜂|  阅读(156)  评论(0编辑  收藏  举报