欧拉序

前置知识

欧拉序

欧拉序所做的,就是在访问节点时记录一遍,每次回溯时再记录一遍。

正片

\(u\)\(v\) 两节点的 LCA 就是欧拉序中 \(u\) 第一次出现的位置和 \(v\) 第一次出现的位置之间的所有节点中深度最浅的点。
证明显然,从 \(u\)\(v\) 会走过 \(lca(u,v)\) 但不会走过 \(lca(u,v)\) 的祖先,因此显然。
代码?没写。
复杂度为 \(O(n\log_2{n}+m)\),但由于欧拉序长度为 \(2n-1\),会有 \(2\) 倍的常数。

dfn 序

前置知识

dfn 序

dfn,即 dfs number,顾名思义,是指在用 dfs 遍历树中每个节点的顺序给节点编的号
graph.png
如图,该树可能的一种 dfn 序如下图
graph (2).png

st 表

见 (还没写)

正片

定义 \(dfn_u\) 为节点 \(u\) 的 dfn 序,\(dep_u\) 为节点 \(u\) 的深度,\(fa_u\) 为节点 \(u\) 的父节点,\(rdfn_u\) 为对应 dfn 序的节点。
那么,当 \(u\ne v\)\(dfn_u<dfn_v\) 时,\(u\)\(v\) 的 LCA 为 dfn 序为 \(dfn_u+1\)\(dfn_v\) 的所有节点中深度最浅的点的父节点。
怎么证明呢,我们分类讨论一下。
\(u\)\(v\) 祖先时,显然。
否则,我们画个图
graph (3).png
其中,dfn 序为 \(dfn_u+1\)\(dfn_v\) 的所有节点为下图中圈出来的点(多圈了 \(3\)\(u\)\(v\) 写成 \(y\) 了)
graph (3).png
此时显然。
复杂度呢?\(O(n\log_2{n}+m)\),由于 \(dfn\) 序长度为 \(n\),因此相比欧拉序常数小 \(\frac{1}{2}\)

code

你很期待这个

#include<cstdio>
#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
const int N=5e5+10;
int lg[N],st[N][20],dfn[N],rdfn[N],fa[N],dep[N];
struct edge{
	int to,nxt;
}g[N<<1];
int head[N],tot;
void add(int u,int v){
	g[tot].to=v;
	g[tot].nxt=head[u];
	head[u]=tot;
	tot++;
	return;
}
int cnt;
void dfs(int u){
	dfn[u]=++cnt;
	rdfn[cnt]=u;
	dep[u]=dep[fa[u]]+1;
	for(int i=head[u];~i;i=g[i].nxt){
		int v=g[i].to;
		if(!dfn[v]){fa[v]=u;dfs(v);}
	}
	return;
}
int main(){
	cin.tie(0);
	ios::sync_with_stdio(false);
	memset(head,-1,sizeof(head));
	int n,m,s;
	cin>>n>>m>>s;
	for(int i=1,x,y;i<n;i++){
		cin>>x>>y;
		add(x,y);
		add(y,x);
	}
	dfs(s);
	for(int i=1;i<=n;i++){
		st[i][0]=rdfn[i];
	}
	for(int i=2;i<=n;i++)lg[i]=lg[i>>1]+1;
	for(int j=1;j<=lg[n];j++){
		for(int i=1;i<=n-(1<<j)+1;i++){
			int x=st[i][j-1],y=st[i+(1<<(j-1))][j-1];
			if(dep[x]<dep[y]){
				st[i][j]=x;
			}else{
				st[i][j]=y;
			}
		}
	}
	while(m--){
		int u,v;
		cin>>u>>v;
		if(u==v){
			cout<<u<<"\n";
			continue;
		}
		int l=min(dfn[u],dfn[v])+1,r=max(dfn[u],dfn[v]);
		int j=lg[r-l+1];
		int x=st[l][j],y=st[r-(1<<j)+1][j];
		cout<<(dep[x]<dep[y]?fa[x]:fa[y])<<"\n";
	}
	return 0;
}
posted on 2025-05-25 15:01  PengDave  阅读(3)  评论(0)    收藏  举报