原题hdu链接 原题poj链接
- 题解:做得比较通透的题,首先知道一条性质,边双连通分量缩点后会变成一棵树。要想知道加边后还有几个桥,那就相当于在一棵树上加边,找到这两个点的最近公共祖先,然后就可以找到经过了多少条边,这些全是桥,并且当经过后,这些桥都不再起作用了。
- 代码:
#include <iostream>
#include <vector>
#include <cstring>
#include <cstdio>
#include <queue>
#include <map>
using namespace std;
const int N = 101000;
const int M = 401000;
int h[M], ne[M], to[M], idx;
int dfn[N], low[N], times;
int stk[N], top;
int id[N];
int ans, e_dcc;
int U[M], V[M];
void add(int u, int v) {ne[idx] = h[u], to[idx] = v, h[u] = idx++;}
void tarjan(int u, int from) {
dfn[u] = low[u] = ++times;
stk[++top] = u;
bool flag = 1;
for (int i = h[u]; i != -1; i = ne[i])
{
int v = to[i];
if ((i^1) == from && flag) {flag = 0;continue;}
if (!dfn[v]) {
tarjan(v, i);
low[u] = min(low[u], low[v]);
if (low[v] > dfn[u]) {
ans++;
}
} else
low[u] = min(low[u], dfn[v]);
}
if (low[u] == dfn[u]) {
e_dcc++;
while (1) {
id[stk[top]] = e_dcc;
if (stk[top--] == u)break;
}
}
}
int dep[N];
int pre[N];
bool bridge[N];
void init() {
memset(h, -1, sizeof h);
memset(dfn, 0, sizeof dfn);
memset(bridge, 0, sizeof bridge);
memset(dep, 0, sizeof dep);
idx = times = ans = e_dcc=top =0;
}
void dfs(int u, int fa) {
if (fa == -1)dep[u] = 1;
else dep[u] = dep[fa] + 1, pre[u] = fa;
for (int i = h[u]; i != -1; i = ne[i]) {
int v = to[i];
if (dep[v] == 0)dfs(v, u);
}
}
void lca(int x, int y) {
if (dep[x] < dep[y])swap(x,y);
while (dep[x] > dep[y]) {
if (bridge[x])bridge[x] = 0,ans--;
x = pre[x];
}
while (x != y) {
if (bridge[x]) bridge[x] = 0, ans--;
x = pre[x];
if (bridge[y]) bridge[y] = 0, ans--;
y = pre[y];
}
}
void solve() {
int n, m;
int cas = 0;
while (~scanf("%d%d", &n, &m)) {
if (n == 0 && m == 0)break;
init();
for (int i = 1; i <= m; i ++) {
scanf("%d%d", &U[i], &V[i]);int u = U[i],v = V[i];
add(u, v);
add(v, u);
}
for (int i = 1; i <= n; i ++) {
if (!dfn[i])tarjan(i, -1);
bridge[i]=1;
dep[i] = 0;
}
memset(h, -1, sizeof h);idx = 0;
for (int i = 1; i <= m; i ++) {
int u = U[i], v = V[i];
if (id[u] == id[v])continue;
add(id[u], id[v]);
add(id[v], id[u]);
}
dfs(1, -1);
int q;scanf("%d", &q);
printf("Case %d:
", ++cas);
while (q--) {
int u, v;scanf("%d%d", &u, &v);
lca(id[u], id[v]);
printf("%d
", ans);
}puts("");
}
}
int main() {
int t = 1;//cin >> t;
while (t--)solve();
return 0;
}