树_最近公共祖先

namespace lca{//树_最近公共祖先 
	
	const int NN=500005;//最大点数 
	const int MM=500005;//最大边数 
	
	int head[NN],N,n;//存图用的,N为点数,N-1条边 
	int d[NN],fa[NN][31];// 点深度(根为1),往上的第2^N个祖先 
	
	struct node{
		int x,nex,d;
	};
	
	node a[MM<<1];
	
	void add(int x,int y,int d){//建边,x->y,长度为d 
		n++;
		a[n].x=y,a[n].d=d,a[n].nex=head[x];
		head[x]=n;
	}
	
	void dfs(int x,int k,int f){
		fa[x][0]=f,d[x]=k;
		for(int i=head[x];i;i=a[i].nex){
			if(a[i].x==f) continue;
			dfs(a[i].x,k+1,x);
		}
	}
	
	void pre(int x){//从根节点x开始预处理 
		for(int i=1;i<=N;++i){
			for(int j=0;j<=30;++j){
				fa[i][j]=-1;
			}
		}
		dfs(x,1,x);
		for(int j=1;j<=30;++j){
			for(int i=1;i<=N;++i){
				if(fa[i][j-1]==-1) continue;
				fa[i][j]=fa[fa[i][j-1]][j-1];
			}
		}
	}
	
	int lca(int x,int y){//返回x,y的最近公共祖先 
		if(d[x]>d[y]) swap(x,y);
		for(int i=30;i>=0;--i){
			int y_=fa[y][i];
			if(y_==-1||d[y_]<d[x]) continue;
			y=y_;
		}
		if(x==y) return x;
		for(int i=30;i>=0;--i){
			int x_=fa[x][i],y_=fa[y][i];
			if(x_==-1||y==-1||x_==y_) continue;
			x=x_,y=y_;
		}
		return fa[x][0];
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值