题目
将图建成圆方树后会发现,必经点数 = 圆方树上两点路径上圆点数。
考虑求路径中的圆点数量。因为起点和终点均为圆点,所以路径 \(x\) 到 \(y\) 的答案即为 \((dis(x,y)+1)/2\)。
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll mod = 1e9 + 7;
const int N = 200005;
const int INF = 0x3f3f3f3f;
int n, m;
int dfn[N], low[N], ck, cnt;
vector<int> G[N], H[N];
stack<int> s;
int vis[N], tot;
void tarjan(int u, int fa) {dfn[u] = low[u] = ++ck;vis[u] = tot;s.push(u);for (auto v : G[u]) {if (!dfn[v]) {tarjan(v, u);low[u] = min(low[u], low[v]);if (low[v] >= dfn[u]) {cnt++;while (1) {int x = s.top();s.pop();H[cnt].push_back(x);H[x].push_back(cnt);if (x == v) break;}H[cnt].push_back(u);H[u].push_back(cnt);}} else if (v != fa){low[u] = min(low[u], dfn[v]);}}
}
int dep[N], fa[N], sz[N], son[N], top[N];
void dfs1(int u) {dfn[u] = ++ck;dep[u] = dep[fa[u]] + 1;sz[u] = 1;for (auto v : H[u]) {if (v == fa[u]) continue;fa[v] = u;dfs1(v);sz[u] += sz[v];if (sz[v] > sz[son[u]]) son[u] = v;}
}
void dfs2(int u, int h) {top[u] = h;if (son[u]) dfs2(son[u], h);for (auto v : H[u]) {if (v == fa[u] || v == son[u]) continue;dfs2(v, v);}
}
int LCA(int x, int y) {while (top[x] != top[y]) {if (dep[top[x]] < dep[top[y]]) swap(x, y);x = fa[top[x]];}return dep[x] < dep[y] ? x : y;
}
int dis(int x, int y) {if (vis[x] != vis[y]) return 0;int ans = dep[x] + dep[y] - 2 * dep[LCA(x, y)];ans = ans / 2 - 1;return ans;
}
struct Node {int x, y;
} bian[N];
int a[N];
int main() {while (scanf("%d%d", &n, &m) != EOF) {if (n == 0 && m == 0) break;while (!s.empty()) {s.pop();}for (int i = 1; i < N; i++) {dfn[i] = low[i] = 0;dep[i] = fa[i] = son[i] = sz[i] = top[i] = 0;vis[i] = 0;G[i].clear();H[i].clear();}ck = 0;tot = 0;for (int i = 1; i <= m; i++) {int u, v;scanf("%d%d", &u, &v);G[u].push_back(v);G[v].push_back(u);bian[i] = {u, v};}cnt = n;for (int i = 1; i <= n; i++) {if (!dfn[i]) {tot++;vis[i] = 1;tarjan(i,-1);dfs1(i);dfs2(i, i);}}ck = 0;int q;scanf("%d", &q);while (q--) {int x, y;scanf("%d%d", &x, &y);int a = bian[x].x, b = bian[x].y, c = bian[y].x, d = bian[y].y;int ans = max(max(dis(b, d), dis(a, d)), max(dis(b, c), dis(a, c)));// printf("#%d\n", LCA(a, b));printf("%d\n", ans);}}return 0;
}