考虑点 p 已被访问,在访问点 q 的时候要回答 LCA(p,q) 的询问。此时与点 p 合并在一起的最高的点 a 一定是 p 的祖先,并且这个 a 还没有遍历完,否则 a 也会被和它的父亲合并。既然如此,q 就必然是这个 a 的子孙。那么,点 a 就是 LCA,因为它是公共祖先,同时不会存在更低的公共祖先,因为更低的公共祖先子孙已经遍历完,不可能是 q 的祖先。
constexprint MXN = 500005; int N, M, S; int head[MXN], to[MXN << 1], nxt[MXN << 1], egsz; int ahead[MXN], ato[MXN << 1], anxt[MXN << 1], asz; int fa[MXN]; bool vis[MXN]; int ans[MXN];
inlinevoidaddedge(int x, int y){ to[egsz] = y, nxt[egsz] = head[x], head[x] = egsz++; to[egsz] = x, nxt[egsz] = head[y], head[y] = egsz++; } inlinevoidaddask(int x, int y){ ato[asz] = y, anxt[asz] = ahead[x], ahead[x] = asz++; ato[asz] = x, anxt[asz] = ahead[y], ahead[y] = asz++; } intfind(int x){ return fa[x] == x ? x : fa[x] = find(fa[x]); } voiddfs(int f, int x){ vis[x] = true; for (inti(head[x]); ~i; i = nxt[i]) { if (to[i] == f) continue; dfs(x, to[i]); fa[find(to[i])] = x; } for (inti(ahead[x]); ~i; i = anxt[i]) { if (!vis[ato[i]]) continue; ans[i >> 1] = find(ato[i]); } } intmain(){ scanf("%d%d%d", &N, &M, &S); --S; fill(head, head + N, -1); fill(ahead, ahead + N, -1); for (inti(0); i != N; ++i) fa[i] = i; for (inti(1), x(0), y(0); i != N; ++i) { scanf("%d%d", &x, &y), --x, --y; addedge(x, y); } for (inti(0), x(0), y(0); i != M; ++i) { scanf("%d%d", &x, &y), --x, --y; addask(x, y); } dfs(-1, S); for (inti(0); i != M; ++i) { ++ans[i], printf("%d\n", ans[i]); } return0; }
constexprint MXN = 500005; constexprint MXLG = 19; int N, M, S; int head[MXN], to[MXN << 1], nxt[MXN << 1], egsz; int depth[MXN], pos[MXN], fa[MXN]; int lg[MXN], seq[MXLG][MXN], sl;
inlineintcmp(int x, int y){ return depth[x] < depth[y] ? x : y; } inlinevoidaddedge(int x, int y){ to[egsz] = y, nxt[egsz] = head[x], head[x] = egsz++; to[egsz] = x, nxt[egsz] = head[y], head[y] = egsz++; } voiddfs(int f, int x, int d){ depth[x] = d; pos[x] = sl; fa[x] = f; seq[0][sl++] = x; for (inti(head[x]); ~i; i = nxt[i]) { if (to[i] == f) continue; dfs(x, to[i], d + 1); } } intquery(int l, int r){ intn(lg[r - l]); returncmp(seq[n][l], seq[n][r - (1 << n)]); }
intmain(){ scanf("%d%d%d", &N, &M, &S); --S; fill(head, head + N, -1); for (inti(1), x(0), y(0); i != N; ++i) { scanf("%d%d", &x, &y), --x, --y; addedge(x, y); } dfs(-1, S, 0); lg[0] = -1, lg[1] = 0; for (inti(2); i <= N; ++i) lg[i] = lg[i >> 1] + 1; for (inti(1); (1 << i) <= N; ++i) { for (intj(0); j + (1 << (i - 1)) <= N; ++j) { seq[i][j] = cmp(seq[i - 1][j], seq[i - 1][j + (1 << (i - 1))]); } } for (intx(0), y(0); M--;) { scanf("%d%d", &x, &y), --x, --y; intans(x ^ y ? fa[query(min(pos[x], pos[y]) + 1, max(pos[x], pos[y]) + 1)] : x); ++ans, printf("%d\n", ans); } return0; }