int n, m, s; int fa[N]; //并查集 bool vst[N]; int tot; int lca[N << 1]; structEdge { int to, nxt; } edge[N << 1], query[N]; int head[N], qhead[N]; voidadd_edge(int u, int v) { edge[tot].to = v; edge[tot].nxt = head[u]; head[u] = tot; tot++; } voidadd_query(int u, int v) { query[tot].to = v; query[tot].nxt = qhead[u]; qhead[u] = tot; tot++; } intfather(int x) { return fa[x] == x ? x : fa[x] = father(fa[x]); } voidtarjan(int rt) { vst[rt] = true; for (int i = head[rt]; ~i; i = edge[i].nxt) if (!vst[edge[i].to]) { tarjan(edge[i].to); fa[edge[i].to] = rt; //回溯时将下面节点的并查集更新 } for (int i = qhead[rt]; ~i; i = query[i].nxt) if (vst[query[i].to]) //回溯时更新所有节点的lca,即回溯的时候并查集的顶端必然不会超过lca lca[i ^ 1] = lca[i] = father(query[i].to); } intmain() { read(n), read(m), read(s); for (int i = 1; i <= n; i++) head[i] = qhead[i] = -1; int u, v; for (int i = 1; i < n; i++) { read(u), read(v); add_edge(u, v); add_edge(v, u); } tot = 0; for (int i = 0; i < m; i++) { read(u), read(v); add_query(u, v); add_query(v, u); } for (int i = 1; i <= n; i++) fa[i] = i; //初始化并查集 tarjan(s); for (int i = 0; i < m; i++) printf("%d\n", lca[i << 1]); return0; }