题目大意:给你一个无向图,其中一个点双联通分量算作一个点,询问两个点之间(包括这两个点)有多少点(注意重边不需要缩点)
题解:$tarjan$缩点,特判一下如果是他的父亲,就不干(去除重边的影响),然后$O(m)$重建图,跑一边$LCA$求距离就好了
卡点:1.没有关注重边
2.查询写成原图中的编号,应为所在联通块的编号
C++ Code:
#include <cstdio> #define maxn 10010 #define maxm 50010 using namespace std; inline int min(int a, int b) {return a < b ? a : b;} int n, m, totq; struct Edge { int from, to, nxt; } ; struct Graph { int head[maxn], cnt; Edge e[maxm << 1]; void add(int a, int b) { e[++cnt] = (Edge) {a, b, head[a]}; head[a] = cnt; } } G1, G2; int low[maxn], DFN[maxn], stack[maxn], tot, idx, cnt; int res[maxn], fa[maxn]; bool ins[maxn]; void tarjan(int u) { low[u] = DFN[u] = ++idx; ins[stack[++tot] = u] = true; int v; for (int i = G1.head[u]; i; i = G1.e[i].nxt) { v = G1.e[i].to; if (!DFN[v]) { fa[v] = u; tarjan(v); low[u] = min(low[u], low[v]); } else { if (v != fa[u]) low[u] = min(low[u], DFN[v]); } } if (DFN[u] == low[u]) { cnt++; do { ins[v = stack[tot--]] = false; res[v] = cnt; } while (v != u); } } int headq[maxn], cntq; struct Query { int to, nxt, t; } Q[10010]; void addq(int a, int b, int c) { Q[++cntq] = (Query) {b, headq[a], c}; headq[a] = cntq; } int ans[maxn], dep[maxn]; int f[maxn]; int find(int x) {return ((x == f[x]) ? x : (f[x] = find(f[x])));} void dfs(int rt) { int v; for (int i = G2.head[rt]; i; i = G2.e[i].nxt) { v = G2.e[i].to; if (!dep[v]) { dep[v] = dep[rt] + 1; dfs(v); f[v] = find(rt); } } for (int i = headq[rt]; i; i = Q[i].nxt) { v = Q[i].to; ans[Q[i].t] = dep[v] + dep[rt] - 2 * dep[find(v)] + 1; } } int s[64], now; void print(int x) { if(!x) { puts("0"); return ; } while(x) s[++now] = x & 1, x >>= 1; while(now) putchar(s[now--] + '0'); putchar(' '); } int main() { scanf("%d%d", &n, &m); for (int i = 0; i < m; i++) { int a, b; scanf("%d%d", &a, &b); G1.add(a, b); G1.add(b, a); } tarjan(1); for (int i = 1; i <= m; i++) { int u = G1.e[i << 1].from, v = G1.e[i << 1].to; if (res[u] != res[v]) { G2.add(res[u], res[v]); G2.add(res[v], res[u]); } } scanf("%d", &totq); for (int i = 1; i <= totq; i++) { int a, b; scanf("%d%d", &a, &b); addq(res[a], res[b], i); addq(res[b], res[a], i); } for (int i = 1; i <= cnt; i++) f[i] = i; dep[1] = 1; dfs(1); for (int i = 1; i <= totq; i++) { print(ans[i]); } return 0; }