1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
| #include <iostream> #include <cstdio> #include <cstring> #include <cctype> using namespace std;
const int MAXN = 500000 + 10; const int MAXM = 500000 + 10;
struct Edge { int prev, next; } edge[MAXM * 2];
int head[MAXN], father[MAXN][22], lg[MAXN], depth[MAXN]; int cnt, n, m, s;
inline int getint() { int s = 0, x = 1; char ch = getchar(); while (!isdigit(ch)) { if (ch == '-') x = -1; ch = getchar(); } while (isdigit(ch)) { s = s * 10 + ch - '0'; ch = getchar(); } return s * x; }
inline void putint(int x, bool returnValue) { if (x < 0) { x = -x; putchar('-'); } if (x >= 10) putint(x / 10, false); putchar(x % 10 + '0'); if (returnValue) putchar('\n'); }
inline void addEdge(int prev, int next) { edge[++cnt].prev = prev; edge[cnt].next = head[next]; head[next] = cnt; }
void dfsInit(int root, int fa) { depth[root] = depth[fa] + 1; father[root][0] = fa; for (int i = 1; (1 << i) <= depth[root]; ++i) { father[root][i] = father[father[root][i-1]][i-1]; } for (int e = head[root]; e; e = edge[e].next) { if (edge[e].prev != fa) dfsInit(edge[e].prev, root); } }
int LCA(int x, int y) { if (depth[x] < depth[y]) swap(x, y); while (depth[x] > depth[y]) x = father[x][lg[depth[x] - depth[y]] - 1]; if (x == y) return x; for (int i = lg[depth[x]]; i >= 0; --i) { if (father[x][i] != father[y][i]) x = father[x][i], y = father[y][i]; } return father[x][0]; }
int main(int argc, char *const argv[]) { n = getint(), m = getint(), s = getint(); for (int i = 1; i < n; ++i) { int prev = getint(), next = getint(); addEdge(prev, next); addEdge(next, prev); } dfsInit(s, 0); for (int i = 1; i <= n; ++i) { lg[i] = lg[i-1] + (1 << lg[i-1] == i); } for (int i = 1; i <= m; ++i) { int x = getint(), y = getint(); putint(LCA(x, y), true); } return 0; }
|