题目大意:基本同上一题[bzoj5329][Sdoi2018]战略游戏,只是每个点集内只有两个点,且只有一组询问而已。(双倍经验?我反正就直接改了一下代码就交了)
题解:同上一题(链接见“题目大意”)
卡点:无
C++ Code:
#include <cstdio> #include <cstring> #define maxn 1000010 #define maxm 1000010 int Tim, n, m, LCA; inline int min(int a, int b) {return a < b ? a : b;} inline void swap(int &a, int &b) {a ^= b ^= a ^= b;} struct Tree { #define root 1 #define fa(u) dad[u][0] #define M 18 int head[maxn], cnt; struct Edge { int to, nxt; } e[maxm << 1]; inline void addE(int a, int b) {e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt;} inline void add(int a, int b) { addE(a, b); addE(b, a); } int dad[maxn][M], dep[maxn], sz[maxn]; int dfn[maxn], idx; void dfs(int u = root) { dfn[u] = ++idx; for (int i = 1; i < M; i++) dad[u][i] = dad[dad[u][i - 1]][i - 1]; for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; if (v != fa(u)) { sz[v] = sz[u] + int(v <= n); // printf("link %d %d ", v, sz[v]); dep[v] = dep[u] + 1; fa(v) = u; dfs(v); } } } inline int LCA(int x, int y) { if (dep[x] < dep[y]) swap(x, y); for (int i = dep[x] - dep[y]; i; i &= i - 1) x = dad[x][__builtin_ctz(i)]; if (x == y) return x; for (int i = M - 1; ~i; i--) if (dad[x][i] != dad[y][i]) x = dad[x][i], y = dad[y][i]; return fa(x); } inline int len(int x, int y) { return sz[x] + sz[y] - (sz[::LCA = LCA(x, y)] << 1); } inline void init() { memset(head, 0, sizeof head); cnt = 0; memset(dfn, 0, sizeof dfn); idx = 0; sz[root] = 0; } #undef root #undef fa #undef M } T; struct Graph { #define root 1 int head[maxn], cnt; struct Edge { int to, nxt; } e[maxm << 1]; inline void addE(int a, int b) {e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt;} inline void add(int a, int b) { addE(a, b); addE(b, a); } int DFN[maxn], low[maxn], idx, CNT; int S[maxn], top, tmp; void tarjan(int u = root) { DFN[u] = low[u] = ++idx; S[++top] = u; for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; if (!DFN[v]) { tarjan(v); low[u] = min(low[u], low[v]); if (low[v] >= DFN[u]) { CNT++; T.add(CNT, u); do { T.add(CNT, tmp = S[top--]); } while (tmp != v); } } else low[u] = min(low[u], DFN[v]); } } inline void init(int n) { memset(head, 0, sizeof head); cnt = 0; memset(DFN, 0, sizeof DFN); idx = 0; CNT = n; } #undef root } G; #define OnlineJudge #define read() R::READ() #include <cctype> namespace R { int x; #ifdef Online_Judge char *ch, op[1 << 26]; inline void init() { fread(ch = op, 1, 1 << 26, stdin); } inline int READ() { while (isspace(*ch)) ch++; for (x = *ch & 15, ch++; isdigit(*ch); ch++) x = x * 10 + (*ch & 15); return x; } #else char ch; inline int READ() { ch = getchar(); while (isspace(ch)) ch = getchar(); for (x = ch & 15, ch = getchar(); isdigit(ch); ch = getchar()) x = x * 10 + (ch & 15); return x; } #endif } int main() { #ifdef Online_Judge R::init(); #endif G.init(n = read()), T.init(); for (int i = m = read(); i; i--) G.add(read(), read()); G.tarjan(); T.dfs(); int Q = read(); while (Q --> 0) printf("%d ", T.len(read(), read()) + int(LCA <= n)); return 0; }