#include <iostream>、
#include<cstring>
using namespace std;
const int N=500002;
const int LM=20;
int n,m,s;
int deep[N];//每个节点在树中的高度层次
int stjump[N][LM];//ST表-第i个点经过2的j次方跳跃能到达的具体点
int cnt=1;
int head[N];
int next1[N<<1];//链式前向星-建无向边-下标为边标记的扩大一倍
int to[N<<1];
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int log2(int n){//根据树的节点数,算出树的高度
int ans=0;
while((1<<ans)<=(n>>1)){//防止溢出的算法N>>1
ans++;
}
return ans;
}
void addedge(int u,int v){
next1[cnt]=head[u];//next-边对边
to[cnt]=v;
head[u]=cnt++;
}
int power=log2(n);
void dfs(int u,int f){//构建deep表和ST表
deep[u]=deep[f]+1;//u子节点深度= f父节点+1
stjump[u][0]=f;//初始化st表,子节点 走一步到父节点
for(int p=1;p<=deep[u];p++){//注意:构建ST表的时候,是递推-从小步--大步,跳跃的时候是从大步开始跳 ,并且当前跳的高度不能超过,当前点的深度
stjump[u][p]=stjump[stjump[u][p-1]][p-1];//构建ST表-u跳8步=u跳4步到达的点再跳4步
}
for(int e=head[u];e!=0;e=next1[e]){
if(to[e]!=f){//注意判断是否为子节点
dfs(to[e],u);//向下深度遍历
}
}
}
int lca(int a,int b){
if(deep[a]<deep[b]){
int temp=a;
a=b;
b=temp;//将两个点的大小深度-确定化方便统一到某个高度 -a一定深
}
for(int p=power;p>=0;p--){
if(deep[stjump[a][p]]>=deep[b]){//将最深的a点统一到b的高度,st表跳跃
a=stjump[a][p];
}
}
if(a==b){
return a;//特判:如果统一到一个高度后两个点相同,说明已经找到最低祖先
}
for(int p=power;p>=0;p--){
if(stjump[a][p]!=stjump[b][p]){//统一到一个高度后一起开始跳跃找公共祖先
a=stjump[a][p];
b=stjump[b][p];
}
}
return stjump[a][0];//说明之前的循环,已经将两个点跳跃到公共祖先的子节点高度,最后只需要跳一步就达到了公共祖先节点
}
int main(int argc, char** argv) {
memset(deep,0,sizeof(deep));
memset(head,0,sizeof(head));
cin>>n>>m>>s;
int a,b;
for(int i=1;i<n;i++){//n-1条边,无向边
cin>>a>>b;
addedge(a,b);
addedge(b,a);
}
dfs(s,s);//构建ST表-可以将初始根节点的父节点设为s,根节点不变仍然会向下遍历
for(int i=1;i<=m;i++){
cin>>a>>b;
cout<<lca(a,b)<<endl;
}
return 0;
}