tarjan
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
const int N=5e5+1145;
int lg[N+100];
int n,m,s;
int fa[N],ans[N];
bool vis[N];
struct Edge{
int to,nex=0,num=0;
}edge[4*N],query[4*N];
int head[N],cnt;
void add_edge(int x,int y){
edge[++cnt].to=x;
edge[cnt].nex=head[y];
head[y]=cnt;
edge[++cnt].to=y;
edge[cnt].nex=head[x];
head[x]=cnt;
return;
}
int head_query[N],cnt_query;
void add_query(int x,int y,int num){
query[++cnt_query].to=x;
query[cnt_query].nex=head_query[y];
query[cnt_query].num=num;
// cout<<x<<" "<<y<<" "<<num<<endl;
head_query[y]=cnt_query;
query[++cnt_query].to=y;
query[cnt_query].nex=head_query[x];
query[cnt_query].num=num;
head_query[x]=cnt_query;
return;
}
int find(int x){
return fa[x]==x?x:fa[x]=find(fa[x]);
}
void tarjan(int pos){
vis[pos]=1;
for(int i=head[pos];i!=0;i=edge[i].nex){
int point=edge[i].to;
// cout<<pos<<":"<<point<<endl;
if(!vis[point]){
tarjan(point);
fa[point]=pos;
}
}
// cout<<pos<<endl;
for(int i=head_query[pos];i!=0;i=query[i].nex){
int point=query[i].to;
if(vis[point]){
ans[query[i].num]=find(point);
}
}
return;
}
signed main(){
// IOS
// freopen("P3379_1.in","r",stdin);
cin>>n>>m>>s;
for(int i=1;i<=n-1;i++){
int x,y;
cin>>x>>y;
add_edge(x,y);
fa[i]=i;
}
fa[n]=n;
for(int i=1;i<=m;i++){
int x,y;
cin>>x>>y;
add_query(x,y,i);
}
tarjan(s);
for(int i=1;i<=m;i++){
cout <<ans[i]<< endl;
}
return 0;
}
倍增
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
const int N=5e5+1145;
int lg[N+100];
int n,m,s;
struct Edge{
int pos,nex=0;
}edge[4*N];
int head[N],cnt;
int deep[N],fa[N][20];
void add_edge(int x,int y){
edge[++cnt].pos=x;
edge[cnt].nex=head[y];
head[y]=cnt;
edge[++cnt].pos=y;
edge[cnt].nex=head[x];
head[x]=cnt;
return;
}
void init(){
//lg初始化
for(int i=2;i<=N;i++){
lg[i]=lg[i>>1]+1;
}
//bfs
queue<int>que;
que.push(s);
deep[s]=1;
while(!que.empty()){
int x=que.front();
que.pop();
int nex=head[x];
while(nex){
int pos=edge[nex].pos;
if(!deep[pos]){
que.push(edge[nex].pos);
deep[pos]=deep[x]+1;
fa[pos][0]=x;
}
nex=edge[nex].nex;
}
}
//倍增表
fa[s][0]=-1;
for(int i=1;i<=lg[N];i++){
fa[s][i]=-1;
for(int j=1;j<=n;j++){
if(fa[j][i-1]!=-1)fa[j][i]=fa[fa[j][i-1]][i-1];
else fa[j][i]=-1;
}
}
}
signed main(){
IOS
// freopen("P3379_1.in","r",stdin);
cin>>n>>m>>s;
for(int i=1;i<=n-1;i++){
int x,y;
cin>>x>>y;
add_edge(x,y);
}
init();
for(int i=1;i<=m;i++){
int a,b;
cin>>a>>b;
if(a==b){
cout<<a<<endl;
continue;
}
if(deep[a]<deep[b])
swap(a,b);
while(deep[a]!=deep[b]){
a=fa[a][lg[deep[a]-deep[b]]];
}
if(a==b){
cout<<a<<endl;
continue;
}
for(int i=lg[deep[a]];i>=0;i--){
if(fa[a][i]!=fa[b][i])a=fa[a][i],b=fa[b][i];
}
cout<<fa[a][0]<<endl;
}
return 0;
}