#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;
}