题面
题解
缩点边双没跑了, 主要是算答案
采用靠并查集爬树的思想
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 << ":
";
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 << '
';
} cout << '
';
}
return 0;
}