题意:一个无向图可以有重边,下面q个操作,每次在两个点间连接一条有向边,每次连接后整个无向图还剩下多少桥(注意是要考虑之前连了的边,每次回答是在上一次的基础之上)
/* tarjan+LCA 先用tarjan缩点,那么这个图就会变成一棵树,当我们连起不在同一节点时,就相当于 把树上的两个节点连了起来,这两个节点同他们的公共祖先会形成一个新的缩点,每次统计 桥的个数。 */ #include<iostream> #include<cstdio> #include<cstring> #define M 200010 using namespace std; int n,m,num,head[M],low[M],dfn[M],topt; int s[M],top,f[M],sum,belong[M],cnt,cas; int Num,Head[M],fa[M],c[M],vis[M]; struct node{int v,pre;}e[M*2]; struct Node{int v,pre;}E[M*2]; void Add(int from,int to) { e[num].v=to; e[num].pre=head[from]; head[from]=num++; } void add(int from,int to) { E[Num].v=to; E[Num].pre=Head[from]; Head[from]=Num++; } void Tarjan(int x,int fa) { low[x]=dfn[x]=++topt; s[++top]=x;f[x]=1; for(int i=head[x];i!=-1;i=e[i].pre) { int v=e[i].v; if(i==(fa^1))continue; if(dfn[v]==0) { Tarjan(v,i);low[x]=min(low[x],low[v]); } else if(f[v])low[x]=min(low[x],dfn[v]); } if(low[x]==dfn[x]) { sum++; while(x!=s[top]) { f[s[top]]=0;belong[s[top]]=sum;top--; } f[s[top]]=0;belong[s[top]]=sum;top--; } } void Dfs(int now,int from,int dep) { fa[now]=from;c[now]=dep; for(int i=Head[now];i!=-1;i=E[i].pre) if(E[i].v!=from) Dfs(E[i].v,now,dep+1); } void LCA(int a,int b) { if(c[a]<c[b])swap(a,b); int t=c[a]-c[b]; for(int i=1;i<=t;i++) { if(vis[a]==0)cnt--; vis[a]=1;a=fa[a]; } while(a!=b) { if(vis[a]==0)cnt--; vis[a]=1;a=fa[a]; if(vis[b]==0)cnt--; vis[b]=1;b=fa[b]; } } int main() { while(1) { scanf("%d%d",&n,&m); if(n==0&&m==0)break; memset(head,-1,sizeof(head)); memset(Head,-1,sizeof(Head)); memset(low,0,sizeof(low)); memset(dfn,0,sizeof(dfn)); memset(f,0,sizeof(f)); memset(belong,0,sizeof(belong)); memset(vis,0,sizeof(vis)); memset(c,0,sizeof(c)); memset(fa,0,sizeof(fa)); memset(s,0,sizeof(s)); Num=num=topt=sum=0; int u,v; for(int i=1;i<=m;i++) { scanf("%d%d",&u,&v); Add(u,v);Add(v,u); } for(int i=1;i<=n;i++) if(dfn[i]==0) Tarjan(i,-1); for(int u=1;u<=n;u++) for(int i=head[u];i!=-1;i=e[i].pre) if(belong[u]!=belong[e[i].v]) add(belong[u],belong[e[i].v]); Dfs(1,1,0);cnt=sum-1; scanf("%d",&m); printf("Case %d:\n",++cas); for(int i=1;i<=m;i++) { scanf("%d%d",&u,&v); int U=belong[u]; int V=belong[v]; if(U==V) { printf("%d\n",cnt);continue; } LCA(U,V); printf("%d\n",cnt); } } return 0; }
时间: 2024-10-13 11:24:20