Network POJ - 3694
阿新 • • 發佈:2020-12-09
題面
題解
縮點邊雙沒跑了, 主要是算答案
採用靠並查集爬樹的思想
int h[N], to[M << 2], ne[M << 2], tot; void add(int u, int v) { ne[++tot] = h[u]; to[h[u] = tot] = v; } int dfn[N], df, st[N], low[N]; int c[N], ecnt, top; void tarjan(int x, int bian) { dfn[st[++top] = x] = low[x] = ++df; for (int i = h[x]; i; i = ne[i]) { int y = to[i]; if (!dfn[y]) tarjan(y, i), umin(low[x], low[y]); else if (i != (bian ^ 1)) umin(low[x], dfn[y]); } if (low[x] == dfn[x]) { ++ecnt; int y; do c[y = st[top--]] = ecnt; while (y != x); } } int f[N], dep[N], ans, pre[N]; int find(int x) { return x == f[x] ? x : f[x] = find(f[x]); } void dfs(int x, int fa) { pre[x] = fa; dep[x] = dep[fa] + 1; for (int i = h[x]; i; i = ne[i]) { int y = to[i]; if (y == fa) continue; dfs(y, x); } } void lca(int x, int y) { x = find(x), y = find(y); while (x != y) { if (dep[x] > dep[y]) { st[++top] = x; x = find(pre[x]); } else { st[++top] = y; y = find(pre[y]); } --ans; } while (top) f[st[top--]] = x; } int main() { IOS; int cas = 0; while (cin >> n >> m, n && m) { cout << "Case " << ++cas << ":\n"; df = ecnt = ans = 0; tot = 1; rep(i, 1, n) h[i] = dfn[i] = 0; rep(i, 1, m) { int u, v; cin >> u >> v; add(u, v); add(v, u); } tarjan(1, -1); rep(i, 1, ecnt) h[i] = 0, f[i] = i; for (int i = tot; i >= 2; i -= 2) { int u = c[to[i ^ 1]], v = c[to[i]]; if (u == v) continue; add(u, v); add(v, u); ++ans; } dfs(1, 0); for (cin >> _; _; --_) { int u, v; cin >> u >> v; lca(c[u], c[v]); cout << ans << '\n'; } cout << '\n'; } return 0; }