最近公共祖先(LCA)

题目

luogu3379

ST表求LCA

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define N 1000005
using namespace std;

int n,m,root,f[N][25];

int num,a[N],b[N],nt[N],p[N];
void add(int x,int y)
{
    a[num++]=x;b[num]=y;
    nt[num]=p[x];p[x]=num;
}

int t,deep[N],dfn[N],la[N];bool flag[N];
void dfs(int k)
{
	flag[k]=1;
	for(int e=p[k];e;e=nt[e])
	{
		int kk=b[e];
		if(flag[kk]) continue;//除去父节点
		deep[kk]=deep[k]+1;
		dfn[++t]=k;
		dfs(kk);
	}
	dfn[++t]=k;la[k]=t;//la[i]记录i最后出现的dfs序 
}

int Min(int x,int y)
{
	if(deep[x]<deep[y]) return x;
	return y;
}

void pre()
{
	for(int i=1;i<=t;i++) f[i][0]=dfn[i];
	for(int j=1;j<=23;j++)
		for(int i=1;i+(1<<j)-1<=t;i++)
		f[i][j]=Min(f[i][j-1],f[i+(1<<j-1)][j-1]);
}

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

int main()
{ 
	n=read();m=read();root=read();
	for(int i=1;i<n;i++)
	{
		int x=read(),y=read();
		add(x,y);add(y,x);
	}
	dfs(root);
	pre();
	for(int i=1;i<=m;i++)
	{
		int x=read(),y=read();
		x=la[x];y=la[y];
		if(x>y) swap(x,y);
		int k=log2(y-x+1);
		printf("%d\n",Min(f[x][k],f[y-(1<<k)+1][k]));
	}
	return 0;
}
posted @ 2017-08-28 15:55  XYZinc  阅读(125)  评论(0编辑  收藏  举报