#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#include<cmath>
using namespace std;
const int M=500001;
int n,m,s,a,b;
int f[M*2],d[M*2],l[M*2],dfn;
bool vis[2*M];
int dp[2*M][20],pos[2*M][20];
struct node
{
int next,to;
}t[M*2],t2[M];
int cnt,head[2*M],head2[2*M];
void add(int u,int v)
{
t[++cnt].next=head[u];
t[cnt].to=v;
head[u]=cnt;
}
void add2(int u,int v)
{
t2[++cnt].next=head2[u];
t2[cnt].to=v;
head2[u]=cnt;
}
void make_tree(int u)
{
vis[u]=1;
for(int i=head[u];i;i=t[i].next)
{
int k=t[i].to;
if(!vis[k])
{
add2(u,k);
make_tree(k);
}
}
}
void dfs(int x,int y)
{
d[++dfn]=y;
f[dfn]=x;
l[x]=dfn;
for(int i=head2[x];i;i=t2[i].next)
{
int k=t2[i].to;
dfs(k,y+1);
d[++dfn]=y;
f[dfn]=x;
}
}
void rmq()
{
for(int i=1;i<=dfn;++i)
dp[i][0]=d[i],pos[i][0]=f[i];
for(int j=1;(1<<j)<=dfn;++j)
for(int i=1;i+(1<<(j-1))<=dfn;++i)
{
dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
if(dp[i][j-1]<dp[i+(1<<(j-1))][j-1])
pos[i][j]=pos[i][j-1];
else pos[i][j]=pos[i+(1<<(j-1))][j-1];
}
}
void find(int i,int j)
{
if(i>j)swap(i,j);
int k=(int)(log((double)(j-i+1))/log(2.0));
int res;
if(dp[i][k]<dp[j+1-(1<<k)][k])//pos[][]的求得依赖于dp[]的求得,因此任何时候都要依托于dp[][]求pos[][].
res=pos[i][k];
else
res=pos[j+1-(1<<k)][k];
printf("%d\n",res);
}
void read(int &a)
{
char c=getchar();
while(!isdigit(c)) c=getchar();//isdigit函数需加头文件cctype
while(isdigit(c))a=a*10+c-48,c=getchar();
}
int main()
{
read(n),read(m),read(s);
for(int i=1;i<=n-1;++i)
{
read(a=0),read(b=0);
add(a,b);
add(b,a);
}
cnt=0;
make_tree(s);
dfs(s,1);
rmq();
for(int i=1;i<=m;++i)
{
read(a=0),read(b=0);
find(l[a],l[b]);
}
}
#include<cstring>
#include<algorithm>
#include<cctype>
#include<cmath>
using namespace std;
const int M=500001;
int n,m,s,a,b;
int f[M*2],d[M*2],l[M*2],dfn;
bool vis[2*M];
int dp[2*M][20],pos[2*M][20];
struct node
{
int next,to;
}t[M*2],t2[M];
int cnt,head[2*M],head2[2*M];
void add(int u,int v)
{
t[++cnt].next=head[u];
t[cnt].to=v;
head[u]=cnt;
}
void add2(int u,int v)
{
t2[++cnt].next=head2[u];
t2[cnt].to=v;
head2[u]=cnt;
}
void make_tree(int u)
{
vis[u]=1;
for(int i=head[u];i;i=t[i].next)
{
int k=t[i].to;
if(!vis[k])
{
add2(u,k);
make_tree(k);
}
}
}
void dfs(int x,int y)
{
d[++dfn]=y;
f[dfn]=x;
l[x]=dfn;
for(int i=head2[x];i;i=t2[i].next)
{
int k=t2[i].to;
dfs(k,y+1);
d[++dfn]=y;
f[dfn]=x;
}
}
void rmq()
{
for(int i=1;i<=dfn;++i)
dp[i][0]=d[i],pos[i][0]=f[i];
for(int j=1;(1<<j)<=dfn;++j)
for(int i=1;i+(1<<(j-1))<=dfn;++i)
{
dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
if(dp[i][j-1]<dp[i+(1<<(j-1))][j-1])
pos[i][j]=pos[i][j-1];
else pos[i][j]=pos[i+(1<<(j-1))][j-1];
}
}
void find(int i,int j)
{
if(i>j)swap(i,j);
int k=(int)(log((double)(j-i+1))/log(2.0));
int res;
if(dp[i][k]<dp[j+1-(1<<k)][k])//pos[][]的求得依赖于dp[]的求得,因此任何时候都要依托于dp[][]求pos[][].
res=pos[i][k];
else
res=pos[j+1-(1<<k)][k];
printf("%d\n",res);
}
void read(int &a)
{
char c=getchar();
while(!isdigit(c)) c=getchar();//isdigit函数需加头文件cctype
while(isdigit(c))a=a*10+c-48,c=getchar();
}
int main()
{
read(n),read(m),read(s);
for(int i=1;i<=n-1;++i)
{
read(a=0),read(b=0);
add(a,b);
add(b,a);
}
cnt=0;
make_tree(s);
dfs(s,1);
rmq();
for(int i=1;i<=m;++i)
{
read(a=0),read(b=0);
find(l[a],l[b]);
}
}