题意;给你一个无向连通图,每次加一条边后,问图中桥的数目
#include <iostream>
#include <cstdio>
#include <cstring>
#include <stack>
using namespace std;
const int M = 400005;
struct node {
int to;
int next;
}num[M];
int ins[M];
int dfn[M];
int low[M];
int head[M];
int isqiao[M];
int Set[M];
int index;
int ans;
int T, n, m, e;
void add(int a, int b) {
num[e].to = b;
num[e].next = head[a];
head[a] = e++;
}
int Find(int x) {
return x == Set[x] ? x : Set[x] = Find(Set[x]);
}
void Union(int x, int y) {
x = Find(x);
Set[y] = x;
}
void Tanjian(int u ,int p) { //缩点,
int v;
Set[u] = u;
dfn[u] = low[u] = index++;
ins[u] = 1;
for(int k = head[u]; k != -1; k = num[k].next) {
v = num[k].to;
if(ins[v] == 1 && v != p) { //防止重边
low[u] = min(low[u], dfn[v]);
}
if(!dfn[v]) {
Tanjian(v, u);
Union(u, v); //使用并查集构建LCA
low[u] = min(low[u], low[v]);
if(low[v] > dfn[u]) { //判断桥的条件,
isqiao[v] = 1;
ans++;
}
}
}
ins[u] = 2;
}
void lca(int x, int y) {
if(dfn[x] < dfn[y]) swap(x, y);
while(dfn[x] > dfn[y]) {
if(isqiao[x]) { //找x和最近根间所有的桥,把他们消去;
ans--;
isqiao[x] = 0;
}
x = Set[x];
}
while(x != y) { //找到y和最近根间的所有桥, 把他们消去;
if(isqiao[y]) {
ans--;
isqiao[y] = 0;
}
y = Set[y];
}
}
int main()
{
int a, b, q = 1;
while (scanf("%d%d", &n, &m) != EOF ) {
if(n == 0 && m == 0)
break;
e = 0;
ans = 0;
index = 1;
memset(head, -1, sizeof(head));
memset(isqiao, 0, sizeof(isqiao));
memset(dfn, 0, sizeof(dfn));
// memset(low, 0, sizeof(low));
memset(ins, 0, sizeof(ins));
for(int i = 0; i < m; i++) {
scanf("%d%d", &a, &b);
add(a, b);
add(b, a);
}
Tanjian(1, -1);
printf("Case %d:\n", q++);
scanf("%d", &T);
for(int i = 0; i < T; i++) {
scanf("%d%d", &a, &b);
lca(a, b);
printf("%d\n", ans);
}
printf("\n");
}
return 0;
}