题意:
给出一张图,Q个询问,每个询问都是在前面询问的基础上,每个询问连一条边,问现在还有几个桥。
题解:
跑一边Tarjan,同时记录桥、父亲的信息,然后对于每个询问找LCA,途经桥,那么桥的数量就减一。
#include<iostream> #include<math.h> #include<stdio.h> #include<algorithm> #include<string.h> #include<vector> #include<queue> #include<map> #include<set> using namespace std; #define B(x) (1<<(x)) typedef long long ll; void cmax(int& a,int b){ if(b>a)a=b; } void cmin(int& a,int b){ if(b<a)a=b; } const int oo=0x3f3f3f3f; const int MOD=1000000007; const int maxn=110000; const int maxm=210000; struct EDGE{ int v,next,c,f; }E[maxm<<1]; int head[maxn],tol; int low[maxn],dfn[maxn]; int isbridge[maxn],fa[maxn]; int g_cnt,bcnt; void Init(){ memset(head,-1,sizeof head); tol=0; memset(low,0,sizeof low); memset(dfn,0,sizeof dfn); memset(isbridge,0,sizeof isbridge); g_cnt=bcnt=0; } void add_edge(int u,int v){ E[tol].v=v; E[tol].next=head[u]; head[u]=tol++; } void Tarjan(int u,int pre){ dfn[u]=low[u]=++g_cnt; for(int i=head[u];i!=-1;i=E[i].next){ int v=E[i].v; if(v==pre)continue; if(!dfn[v]){ fa[v]=u; Tarjan(v,u); if(low[v]<low[u]) low[u]=low[v]; if(low[v]>dfn[u]){ bcnt++; isbridge[v]=1; } }else if(dfn[v]<low[u]) low[u]=dfn[v]; } } void LCA(int u,int v){ if(dfn[u]<dfn[v])swap(u,v); while(dfn[u]>dfn[v]){ if(isbridge[u])bcnt--; isbridge[u]=0; u=fa[u]; } while(u!=v){ if(isbridge[u])bcnt--; if(isbridge[v])bcnt--; isbridge[u]=isbridge[v]=0; u=fa[u]; v=fa[v]; } } int main(){ //freopen("E:\\read.txt","r",stdin); int n,m,u,v,Q; int cas=1; while(scanf("%d %d",&n,&m)!=EOF){ if(n==0&&m==0)break; Init(); for(int i=1;i<=m;i++){ scanf("%d %d",&u,&v); add_edge(u,v); add_edge(v,u); } fa[1]=1; Tarjan(1,-1); scanf("%d",&Q); printf("Case %d:\n",cas++); while(Q--){ scanf("%d %d",&u,&v); LCA(u,v); printf("%d\n",bcnt); } puts(""); } return 0; }