思路:题目的意思是要求在原图中加边后桥的数量,首先我们可以通过Tarjan求边双连通分量,对于边(u,v),如果满足
low[v]>dfn[u],则为桥,这样我们就可以知道图中桥的数目了。对于每一次query,可以考虑dfs树,树边肯定是桥,然后连
上u,v这条边之后,就会形成一个环,这样环内的边就不是割边了,所以只要找到u,v的LCA,把这个路径上的桥标记为否就可以了。
const int maxn = 1e5 + 10;
vector<vector<int> > G;
int dfn[maxn], low[maxn], isbridge[maxn], mark[maxn], depth;
int pre[maxn];
int bridge_cnt;
void dfs(int u, int fa) {
dfn[u] = low[u] = ++depth;
mark[u] = 1;
int first = 1;
int size = G[u].size();
for (int i = 0;i < size;++i) {
int v = G[u][i];
if (first && v == fa) {
first = 0;
continue;
}
if (dfn[v] == -1) {
pre[v] = u;
dfs(v, u);
low[u] = min(low[u], low[v]);
if (low[v] > dfn[u]) {//is bridge
isbridge[v] = 1;
bridge_cnt++;
}
}else if (mark[v]) low[u] = min(low[u], dfn[v]);
}
}
int calc(int u,int v) {
int ret = 0;
if (dfn[u] < dfn[v]) swap(u, v);
while(dfn[u] > dfn[v]) {
if (isbridge[u]) {
isbridge[u] = 0;
ret++;
}
u = pre[u];
}
while(dfn[v] > dfn[u]) {
if (isbridge[v]) {
isbridge[v] = 0;
ret++;
}
v = pre[v];
}
// while(u != v) {
// if (isbridge[u]) {isbridge[u] = 0,ret++;}
// if (isbridge[v]) {isbridge[v] = 0,ret++;}
// u = pre[u];
// v = pre[v];
// }
return ret;
}
/*
int calc(int u,int v) {
int ret = 0;
// if (dfn[u] < dfn[v]) swap(u, v);
while(dfn[u] > dfn[v]) {
if (isbridge[u]) {
isbridge[u] = 0;
ret++;
}
u = pre[u];
}
while(dfn[v] > dfn[u]) {
if (isbridge[v]) {
isbridge[v] = 0;
ret++;
}
v = pre[v];
}
while(u != v) {
if (isbridge[u]) {isbridge[u] = 0,ret++;}
if (isbridge[v]) {isbridge[v] = 0,ret++;}
u = pre[u];
v = pre[v];
}
return ret;
}
*/
int main(int argc, const char * argv[])
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
// clock_t _ = clock();
int n, m;
while(scanf("%d%d", &n, &m) != EOF && n + m) {
G.clear();
G.resize(n + 2);
int u, v;
for (int i = 1;i <= m;++i) {
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
memset(dfn, -1,sizeof dfn);
memset(isbridge, 0, sizeof isbridge);
memset(mark, 0,sizeof mark);
depth = 0, bridge_cnt = 0;
dfs(1, -1);
scanf("%d", &m);
printf("Case %d:\n", ++nCase);
while(m--) {
scanf("%d%d", &u, &v);
int cnt = calc(u, v);
bridge_cnt -= cnt;
printf("%d\n", bridge_cnt);
}
printf("\n");
}
// printf("\nTime cost: %.2fs\n", 1.0 * (clock() - _) / CLOCKS_PER_SEC);
return 0;
}