#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e5 + 5;             		         // 最大节点数
struct Edge {                		                 // 图的边结构体(链式前向星存储)
	int v, next;                                     // 邻接节点 下条边的索引
} e1[maxn << 1];                       		         // 双向边,需两倍空间
int head1[maxn], ecnt1;                              // 第一条边索引 边计数器
struct Query {                           		     // 查询结构体(链式前向星存储)
	int v, id, next;                                 // 查询的另一个节点 查询编号 下一条查询的索引
} e2[maxn << 1];                             		 // 双向查询,需两倍空间
int head2[maxn], ecnt2;                              // 第一条查询索引 查询计数器
bool vis[maxn];                                  	 // 标记节点是否被访问过
int fa[maxn], res[maxn];                             // 并查集父节点数组 存储查询结果
int n, m, s;                                  		 // 节点数 查询数 根节点
void init() {                                 		 // 初始化函数
	memset(head1, -1, sizeof(head1));         	 	 // 初始化图的邻接表头为-1
	ecnt1 = 0;                                		 // 边计数器归零
	memset(head2, -1, sizeof(head2));         		 // 初始化查询的邻接表头为-1
	ecnt2 = 0;                                	 	 // 查询计数器归零
	memset(vis, 0, sizeof(vis));              		 // 初始化访问标记数组为0
	for (int i = 1; i <= n; i++) {            		 // 初始化并查集,每个节点的父节点指向自己
		fa[i] = i;
	}
}
void addEdge(int u, int v) {                  		 // 添加双向图的边(u<->v)
	e1[ecnt1] = {v, head1[u]};                		 // 创建从u到v的边
	head1[u] = ecnt1;                         		 // 更新u的邻接表头指针
	ecnt1++;                                  		 // 边计数器加1
	e1[ecnt1] = {u, head1[v]};                		 // 创建从v到u的边
	head1[v] = ecnt1;                         		 // 更新v的邻接表头指针
	ecnt1++;                                  		 // 边计数器加1
}
void addQuery(int u, int v, int id) {         		 // 添加双向查询(u<->v,查询编号为id)
	e2[ecnt2] = {v, id, head2[u]};            		 // 创建从u到v的查询
	head2[u] = ecnt2;                         		 // 更新u的查询表头指针
	ecnt2++;                                  		 // 查询计数器加1
	e2[ecnt2] = {u, id, head2[v]};            		 // 创建从v到u的查询
	head2[v] = ecnt2;                         		 // 更新v的查询表头指针
	ecnt2++;                                  		 // 查询计数器加1
}
int find(int x) {                             		 // 并查集查找函数(带路径压缩)
	if (x == fa[x]) {                         		 // 如果x是所在集合的代表元
		return x;                             		 // 直接返回x
	}
	return fa[x] = find(fa[x]);     	          	 // 递归查找并压缩路径
}
void tarjan(int u) {                          		 // Tarjan离线LCA算法核心函数
	vis[u] = true;                            		 // 标记当前节点u为已访问
	for (int i = head1[u]; i != -1; i = e1[i].next) {// 遍历u的所有邻接节点(子节点)
		int v = e1[i].v;                      		 // 获取邻接节点v
		if (vis[v]) continue;    		             // 如果v已经访问过(说明是父节点),跳过父节点
		tarjan(v);                  	             // 递归处理子节点v
		fa[v] = u;                            		 // 将v所在的集合合并到u(设置v的父节点为u)
	}
	for (int i = head2[u]; i != -1; i = e2[i].next) {// 遍历所有与u相关的查询
		int v = e2[i].v;                      		 // 获取查询的另一个节点v
		if (vis[v]) {                         		 // 如果v已经访问过
			res[e2[i].id] = find(v);          		 // 查询的LCA就是v所在集合的代表元(find(v))
		}
	}
}
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m >> s;
	init();                                  		 // 初始化相关数据结构
	for (int i = 1; i < n; i++) {             		 // 读入n-1条边
		int u, v;
		cin >> u >> v;
		addEdge(u, v);                        		 // 添加双向边
	}
	for (int i = 1; i <= m; i++) {            		 // 读入m个查询
		int u, v;
		cin >> u >> v;
		
		addQuery(u, v, i);                    		 // 添加双向查询,查询编号为i
	}
	tarjan(s);                                		 // 从根节点开始执行Tarjan离线LCA算法
	for (int i = 1; i <= m; i++) {            		 // 输出所有查询结果
		cout << res[i] << "\n";
	}
	return 0;
}