#include using namespace std; typedef pair PII; const int N = 500010, M = N << 1; // 链式前向星 int e[M], h[N], idx, w[M], ne[M]; void add(int a, int b, int c = 0) { e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++; } vector query[N]; // query[u]: first:询问的另一个顶点; second:询问的编号 int n, m, s; int p[N]; // 并查集数组 bool st[N]; // tarjan算法求lca用到的是否完成访问的标识 int lca[N]; // 结果数组 int find(int x) { if (p[x] != x) p[x] = find(p[x]); // 路径压缩 return p[x]; } void tarjan(int u) { // ① 标识u已访问 st[u] = true; // ② 枚举u的临边,tarjan没有访问过的点 for (int i = h[u]; ~i; i = ne[i]) { int j = e[i]; if (!st[j]) { tarjan(j); // ③ 完成访问后,j点加入u家族 p[j] = u; } } // ④ 每个已完成访问的点,记录结果 for (auto q : query[u]) { int v = q.first, id = q.second; if (st[v]) lca[id] = find(v); } } int main() { memset(h, -1, sizeof h); scanf("%d %d %d", &n, &m, &s); int a, b; for (int i = 1; i < n; i++) { scanf("%d %d", &a, &b); add(a, b), add(b, a); } for (int i = 1; i <= m; i++) { scanf("%d %d", &a, &b); query[a].push_back({b, i}); query[b].push_back({a, i}); } // 初始化并查集 for (int i = 1; i <= n; i++) p[i] = i; tarjan(s); // 输出答案 for (int i = 1; i <= m; i++) printf("%d\n", lca[i]); return 0; }