题意:
给一个连通图,问再加入边的过程中,桥的个数。
分析:
对原图进行缩点,形成一棵树,同时边都是桥,然后加入边以后,查询LCA,LCA上的桥都减掉,标记边为桥不方便,直接标记桥的终点就可以了。
#include<cstring>
#include<cstdio>
#include<queue>
#include<vector>
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
struct node{
int to,next;
bool cut;
}edge[maxm];
int head[maxn],tot;
int low[maxn],dfn[maxn],sta[maxn],belong[maxn];
int index,top;
int block;
int du[maxn];
bool instack[maxn];
int bridge;
void addedge(int u,int v){
edge[tot].to=v;
edge[tot].next=head[u];
head[u]=tot++;
}
void tarjan(int u,int pre){
int v;
low[u]=dfn[u]=++index;
sta[top++]=u;
instack[u]=true;
int pre_cnt=0;
for(int i=head[u];i!=-1;i=edge[i].next){
v=edge[i].to;
if(v==pre&&pre_cnt==0){
pre_cnt++;
continue;
}
if(!dfn[v]){
tarjan(v,u);
if(low[u]>low[v]) low[u]=low[v];
if(low[v]>dfn[u]){
++bridge;
edge[i].cut=true;
edge[i^1].cut=true;
}
}else if(instack[v]&&low[u]>dfn[v]){
low[u]=dfn[v];
}
}
if(low[u]==dfn[u]){
block++;
do{
v=sta[--top];
instack[v]=false;
belong[v]=block;
}while(v!=u);
}
}
void init(){
block=top=tot=index=0;
memset(head,-1,sizeof head);
memset(dfn,0,sizeof dfn);
memset(instack,0,sizeof instack);
memset(du,0,sizeof du);
}
int a[maxn];
vector<int> vec[maxn];
int dep[maxn];
int fa[maxn];
int ans;
void lca_bfs(int root){
memset(dep,-1,sizeof dep);
dep[root]=0;
a[root]=0; //标记桥
fa[root]=-1;
queue<int> q;
q.push(root);
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=0;i<vec[u].size();i++){
int v=vec[u][i];
if(dep[v]!=-1) continue;
dep[v]=dep[u]+1;
a[v]=1;
fa[v]=u;
q.push(v);
}
}
}
void lca(int u,int v){
if(dep[u]>dep[v]) swap(u,v);
while(dep[u]<dep[v]){
if(a[v]){
ans--;
a[v]=0;
}
v=fa[v];
}
while(u!=v){
if(a[u]){
ans--;
a[u]=0;
}
if(a[v]){
ans--;
a[v]=0;
}
v=fa[v];
u=fa[u];
}
}
int main(){
int n,m;
int cs=1;
while(scanf("%d%d",&n,&m)!=EOF&&(n||m)){
init();
while(m--){
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
tarjan(1,0);
ans=block-1;
for(int i=1;i<=block;i++){
vec[i].clear();
}
for(int u=1;u<=n;u++){
for(int i=head[u];i!=-1;i=edge[i].next){
if(edge[i].cut){
int v=edge[i].to;
vec[belong[u]].push_back(belong[v]);
vec[belong[v]].push_back(belong[u]);
}
}
}
lca_bfs(1);
int q;
printf("Case %d:\n",cs++);
scanf("%d",&q);
while(q--){
int u,v;
scanf("%d%d",&u,&v);
lca(belong[u],belong[v]);
printf("%d\n",ans);
}
printf("\n");
}
return 0;
}