双连通缩点后的图上任意边都是桥,且它是一棵树。
由此可知,若新加的一条边处于同一个双联通分量,那么答案不变。
否则,新加的边使得树上多出了一个环,且环上的桥都没有了,所以这两点路径上的边都要减少,预处理每个点的父亲和深度,那么求两点的路径直接暴力向上爬就行了,注意标记边只能减少一次。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<map>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define maxn 100005
#define maxm 2000005
struct node
{
int to,vis,next;
}e[maxm],e2[maxm];
int belong[maxn],vis[maxn],dfn[maxn],low[maxn],cnt,bridge,col,stack[maxn],top,fa[maxn],head[maxn],head2[maxn],en,en2,ans;
bool use[maxm];
int n,m;
int dep[maxn];
void add(int a,int b)
{
e[en].to=b;
e[en].vis=0;
e[en].next=head[a];
head[a]=en++;
}
void add2(int a,int b)
{
e2[en2].to=b;
e2[en2].next=head2[a];
head2[a]=en2++;
}
void init()
{
top=cnt=col=bridge=en2=en=0;
memset(vis,0,sizeof(vis));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(use,0,sizeof(use));
memset(head2,-1,sizeof(head2));
memset(head,-1,sizeof(head));
}
void Tarjan (int u)
{
int v;
vis[u] = 1;
dfn[u] = low[u] = ++cnt;
stack[top++] = u;
for (int i = head[u];i != -1;i = e[i].next)
{
v = e[i].to;
if (e[i].vis) continue;
e[i].vis = e[i^1].vis = 1;
if (vis[v] == 1)
low[u] = min(low[u],dfn[v]);
if (!vis[v])
{
Tarjan (v);
low[u] = min(low[u],low[v]);
if (low[v] > dfn[u])
bridge ++;
}
}
if (dfn[u] == low[u])
{
++col;
do{
v = stack[--top];
vis[v] = 0;
belong[v] = col;
}while (u != v);
}
}
void dfs(int now)
{
for(int i=head2[now];~i;i=e2[i].next)
{
int to=e2[i].to;
if(to!=fa[now])
{
dep[to]=dep[now]+1;
fa[to]=now;
dfs(to);
}
}
}
void cal(int a,int b)
{
if(a==b) return;
int root=belong[a];//小优化,可不加
while(a!=b)
{
if(dep[a]<dep[b]) swap(a,b);
if(use[a]==0) ans--;
use[a]=1;
a=fa[a];
belong[a]=root;
}
}
inline int ReadInt()
{
char ch = getchar();
int data = 0;
while (ch < '0' || ch > '9')
{
ch = getchar();
}
do
{
data = data*10 + ch-'0';
ch = getchar();
}while (ch >= '0' && ch <= '9');
return data;
}
int main()
{
int a,b,q,ca=1;
while(~scanf("%d%d",&n,&m))
{
if(!n&&!m) break;
init();
for(int i=1;i<=m;i++)
{
a=ReadInt();
b=ReadInt();
add(a,b);
add(b,a);
}
Tarjan(1);
ans=col-1;
for(int i=1;i<=n;i++)
{
for(int j=head[i];~j;j=e[j].next)
{
int to=e[j].to;
if(belong[to]!=belong[i])
{
add2(belong[i],belong[to]);
}
}
}
dep[1]=0;
fa[1]=-1;
dfs(1);
q=ReadInt();
printf("Case %d:\n",ca++);
while(q--)
{
a=ReadInt();
b=ReadInt();
cal(belong[a],belong[b]);
printf("%d\n",ans);
}
puts("");
}
return 0;
}