//tarjan牛逼
#include<cstdio>
#include<iostream>
#include<string.h>
using namespace std;
const int maxn = 500000+100;
const int maxq = 500010;
int F[maxn];
int find(int x){//找到祖先
if(F[x]==-1){
return x;
}
return F[x] = find(F[x]);
}
void bing(int u,int v){//合并
int t1 = find(u);
int t2 = find(v);
if(t1!=t2)
F[t1]=t2;
}
bool vis[maxn];
int an[maxn];
struct Edge{
int to,next;
}edge[maxn*2];
int head[maxn],tot;
void addedge(int u, int v){
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
struct Query{
int q,next;
int index;
}query[maxq*2];
int answer[maxq];
int h[maxq];
int tt;
int Q;
void add_query(int u,int v,int index){
query[tt].q = v;
query[tt].next = h[u];
query[tt].index = index;
h[u]=tt++;
query[tt].q = u;
query[tt].index = index;
query[tt].next = h[v];
h[v] = tt++;
}
void init(){
tot = 0;
memset(head,-1,sizeof(head));
tt = 0;
memset(h,-1,sizeof(h));
memset(vis,false,sizeof(vis));
memset(F,-1,sizeof(F));
memset(an,0,sizeof(an));
}
void LCA(int u){
an[u] = u;
vis[u] = true;
for(int i =head[u];i!=-1;i = edge[i].next){
int v = edge[i].to;
if(vis[v])continue;//如果v被访问过就跳过 一般不会
LCA(v);//递归先访问v
bing(u,v);//合并u,v 无所谓u加到v上还是v加到u上
an[find(u)] = u;//这一个集合的祖先都是u 因为这个是按照深度优先逐层查找的
//如果在这个深度之下有两个点查询 那么两个点早就被处理掉了
//所以如果回溯到了u那么要查询的两个点肯定不在u的同一个分支上(标重点)
}
for(int i = h[u];i!=-1;i = query[i].next){
int v = query[i].q;
if(vis[v]){//如果v被访问过那么返回v所在的的集合的祖先
answer[query[i].index] = an[find(v)];
}
}
}
bool flag[maxn];
int count_num[maxn];
int main(){
int n;
int u,v,k;
int m,s;
scanf("%d%d%d",&n,&m,&s);
init();
memset(flag,false,sizeof(flag));
for(int i =1;i<n;++i){
scanf("%d",&u);
scanf("%d",&v);
flag[v] = true;
addedge(u,v);
addedge(v,u);
}
for(int i =0;i<m;++i){
scanf("%d %d",&u, &v);
add_query(u,v,i);
}
int root = s;
//cout<<root<<": "<<endl;
LCA(root);
for(int i =0;i<m;++i){
printf("%d\n",answer[i]);
}
}