#include <iostream> #include <cstdio> #include <sstream> #include <cstring> #include <map> #include <set> #include <vector> #include <stack> #include <queue> #include <algorithm> #include <cmath> #define rap(i, a, n) for(int i=a; i<=n; i++) #define MOD 2018 #define LL long long #define ULL unsigned long long #define Pair pair<int, int> #define mem(a, b) memset(a, b, sizeof(a)) #define _ ios_base::sync_with_stdio(0),cin.tie(0) //freopen("1.txt", "r", stdin); using namespace std; const int maxn = 5e5 + 10, INF = 0x7fffffff; const int maxm = 1e6 + 10; int n, m, cnt1, cnt2, c; int head1[maxm], head2[maxm], f[maxm], vis[maxm]; int res[maxm]; struct node { int v, next; }Node[maxm]; struct edge { int v, id, next; }Edge[maxm]; void add1_(int u, int v) { Node[cnt1].v = v; Node[cnt1].next = head1[u]; head1[u] = cnt1++; } void add1(int u, int v) { add1_(u, v); add1_(v, u); } void add2_(int u, int v, int id) { Edge[cnt2].v = v; Edge[cnt2].id = id; Edge[cnt2].next = head2[u]; head2[u] = cnt2++; } void add2(int u, int v, int id) { add2_(u, v, id); add2_(v, u, id); } int find(int x) { return f[x]==x?x:(f[x] = find(f[x])); } int lca(int u)//把整棵树的一部分看作以节点x为根节点的小树 { f[u] = u; //由于节点u被看作是根节点,所以把u的father设为它自己 vis[u] = 1; //标记为已被搜索过 for(int i=head1[u]; i!=-1; i=Node[i].next) //遍历所有与x相连的节点 { node e = Node[i]; //若未被搜索 if(vis[e.v] == -1) { lca(e.v); //以该节点为根节点搞小树 f[e.v] = u; //回溯回来后更新子结点的f } } for(int i=head2[u]; i!=-1; i=Edge[i].next) //搜索包含节点u的所有询问 { edge e = Edge[i]; if(vis[e.v] != -1) //如果另一节点已被搜索过 只有另一结点被搜索过 那一条路径的f才会更新 { int k = find(e.v); //寻找最近公共祖先 res[e.id] = k; } } } void init() { mem(head1, -1); mem(head2, -1); mem(res, -1); mem(vis, -1); cnt1 = cnt2 = 0; } int main() { while(scanf("%d%d%d", &n, &m, &c) != EOF) { init(); int u, v; rap(i, 1, n-1) { scanf("%d%d", &u, &v); add1(u, v); } rap(i, 1, m) { scanf("%d%d", &u, &v); add2(u, v, i); } lca(c); rap(i, 1, m) { if(res[i] == -1) printf("Not connected\n"); else printf("%d\n", res[i]); } } return 0; }