tarjan求双联通(含重边)+ LCA定义求法
#include<cstdio> #include<cstring> #include<algorithm> #define N 100100 #define M 200100 using namespace std; int head[N],cnt,num,depth; int dfn[N],low[N],fa[N],Dfn[N]; bool yes[N]; struct Edge{ int v,next; }edge[M*2]; void addedge(int u,int v){ edge[cnt].v=v; edge[cnt].next=head[u]; head[u]=cnt++; edge[cnt].v=u; edge[cnt].next=head[v]; head[v]=cnt++; } void init(){ memset(head,-1,sizeof(head)); memset(dfn,0,sizeof(dfn)); memset(dfn,0,sizeof(dfn)); memset(yes,0,sizeof(yes)); fa[1]=1,dfn[0]=0; cnt=num=depth=0; } void tarjan(int u,int fat){ int i,flag=1; dfn[u]=low[u]=++depth; Dfn[u]=Dfn[fat]+1; for(i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if(v==fat && flag){ flag=0; continue; } if(dfn[v]==0){ fa[v]=u; tarjan(v,u); low[u]=min(low[u],low[v]); if(low[v]>dfn[u]){ yes[v]=1; num++; } } else low[u]=min(low[u],dfn[v]); } } void LCA(int u,int v){ if(Dfn[u]<Dfn[v])swap(u,v); while(Dfn[u]>Dfn[v]){ if(yes[u]){ num--; yes[u]=0; } u=fa[u]; } while(u!=v){ if(yes[u]){ num--; yes[u]=0; } if(yes[v]){ num--; yes[v]=0; } u=fa[u],v=fa[v]; } } int main(){ int i,n,m,Q; int u,v; int cas=0; while(scanf("%d %d",&n,&m)){ if(n==0 && m==0)break; init(); for(i=1;i<=m;i++){ scanf("%d %d",&u,&v); addedge(u,v); } tarjan(1,0); scanf("%d",&Q); printf("Case %d:\n",++cas); for(i=1;i<=Q;i++){ scanf("%d %d",&u,&v); LCA(u,v); printf("%d\n",num); } } return 0; }