题目大意:给你一个无向图,其中一个点双联通分量算作一个点,询问两个点之间(包括这两个点)有多少点(注意重边不需要缩点)
题解:$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('\n');
}
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;
}