tarjan模板
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define maxn 1000010
using namespace std;
int n,m,s,cnt,tot;
struct arr{
int nd,nx,num;
}bot[maxn],bot_ask[maxn];
int head[maxn],head_ask[maxn];
int fa[maxn],ans[maxn],vis[maxn];
void add_edge(int x,int y)
{bot[++cnt].nd=y; bot[cnt].nx=head[x]; head[x]=cnt; }
{bot_ask[++tot].nd=y;bot_ask[tot].nx=head_ask[x];
bot_ask[tot].num=num;head_ask[x]=tot;}
int gf(int x){ return fa[x]==x?x:fa[x]=gf(fa[x]);}//找爸爸
/*void dfs(int u){
vis[u]=1;//记录是否被搜索过
for(int i=head_ask[u];i;i=bot_ask[i].nx)
if(vis[bot_ask[i].nd])ans[bot_ask[i].num]=gf(bot_ask[i].nd);
//如果该点的询问对象被访问过,那吗他们的最近公共最先就是询问对象的祖先
for(int i=head[u];i;i=bot[i].nx)
if(!vis[bot[i].nd]) dfs(bot[i].nd),fa[bot[i].nd]=u;
//如果该节点没有被搜索过,继续递归下去。回溯的时候将爸爸修改一下
}*/
void dfs(int u) {
vis[u]=1;
for(register int i=head_ask[u];i;i=bot_ask[i].nx)
if(vis[bot_ask[i].nd]) ans[bot_ask[i].num]=gf(bot_ask[i].nd);
for(register int i=head[u];i;i=bot[i].nx)
if(!vis[bot[i].nd])dfs(bot[i].nd),fa[bot[i].nd]=u;
}
inline int read(){
int x=0,w=1;char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') w=-1,ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch-48),ch=getchar();
return x*w;
}
int main()
{
int x,y;
n=read();m=read();s=read();
for(int i=1;i<=n;i++) fa[i]=i;
{int x,y;x=read(),y=read(),add_edge(x,y),add_edge(y,x); }
for(int i=1;i<=m;i++)
{ int x,y;x=read(),y=read(),add_ask(x,y,i),add_ask(y,x,i); }
dfs(s);
for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
return 0;
}
倍增模板
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
struct arr{
int nd,nx;
}bot[1000010];
int n,m,s,cnt,mm,stepp;
int head[500050],dep[500050],fa[500050][22];
inline int read(){
int x=0,w=1;char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') w=-1,ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch-48),ch=getchar();
return x*w;
}
inline void ad1(int a,int b)
{ bot[++cnt].nd=b; bot[cnt].nx=head[a]; head[a]=cnt;}
void dfs(int u){
for(register int i=head[u];i;i=bot[i].nx) {
int v=bot[i].nd;
if(!dep[v]) {
dep[v]=dep[u]+1; mm=max(mm,dep[v]); fa[v][0]=u;
dfs(v);
}
}
}
/*nline void init(){
for(register int j=1;j<=stepp;++j)
for(register int i=1;i<=n;++i)
fa[i][j]=fa[fa[i][j-1]][j-1];
}*/
/*inline int lca(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
for(register int j=stepp;j>=0;--j)
if(dep[fa[x][j]]>=dep[y]) x=fa[x][j];
if(x==y) return x;
for(register int j=stepp;j>=0;--j)
if(fa[x][j]!=fa[y][j]) x=fa[x][j],y=fa[y][j];
return fa[x][0];
}*/
inline void init() {
for(register int j=1;j<=stepp;++j)
for(register int i=1;i<=n;++i)
fa[i][j]=fa[fa[i][j-1]][j-1];
}
inline int lca(int u,int v){
if(dep[u]<dep[v]) swap(u,v);
for(register int j=stepp;j>=0;--j)
if(dep[fa[u][j]]>=dep[v]) u=fa[u][j];
if(u==v) return u;
for(register int j=stepp;j>=0;--j)
if(fa[u][j]!=fa[v][j])u=fa[u][j],v=fa[v][j];
return fa[u][0];
}
int main(){
n=read();m=read();s=read();
for(register int i=1;i<=n-1;++i){
int u=read(),v=read();
ad1(u,v);ad1(v,u);
}
dep[s]=1;
dfs(s);
stepp=log2(mm);
init();
for(register int i=1;i<=m;++i) {
int u=read(),v=read();
printf("%d\n",lca(u,v));
}
return 0;
}