在给出的两个点上加一条边,求剩下桥的数量,,不会LCA在线,就用了最普通的,先Tarjan双联通缩点,然后将缩完的图建成一棵树,树的所有边就是桥了,如果在任意两点间加一条边的话,那么从两点到最近公共祖先的所有边都不是桥了。。。。。。
#pragma comment(linker, "/STACK:10240000000000,10240000000000") #include<stdio.h> #include<stack> #include<string.h> #define N 100010 using namespace std; int belong[N],low[N],dfs[N],head[N],num,n,idx,ans,nume,vis[N]; struct edge { int st,ed,next; }E[N*4],e[N*4]; void addedge(int x,int y) { E[num].st=x; E[num].ed=y; E[num].next=head[x]; head[x]=num++; } void Addedge(int x,int y) { e[nume].st=x; e[nume].ed=y; e[nume].next=head[x]; head[x]=nume++; } stack<int>Q; void Tarjan(int u,int father) { int i,v,flag=0; low[u]=dfs[u]=idx++; Q.push(u); for(i=head[u];i!=-1;i=E[i].next) { v=E[i].ed; if(dfs[v]==-1) { Tarjan(v,u); low[u]=low[u]>low[v]?low[v]:low[u]; } else if(v==father) { if(flag) low[u]=low[u]>dfs[v]?dfs[v]:low[u]; flag++; } else low[u]=low[u]>dfs[v]?dfs[v]:low[u]; } if(low[u]==dfs[u]) { do { v=Q.top(); Q.pop(); belong[v]=ans; }while(v!=u); ans++; } } void dfs1(int u) { vis[u]=1; int i,v; for(i=head[u];i!=-1;i=e[i].next) { v=e[i].ed; if(vis[v]==1)continue; dfs[v]=dfs[u]+1; low[v]=u; dfs1(v); } } void Lca(int x,int y) { int i; if(dfs[x]<dfs[y]) {i=x;x=y;y=i;} while(dfs[x]>dfs[y]) { if(vis[x]==0) { vis[x]=1; ans--; } x=low[x]; } while(x!=y) { if(vis[x]==0) { vis[x]=1; ans--; } if(vis[y]==0) { vis[y]=1; ans--; } x=low[x];y=low[y]; } } int main() { int i,k,x,y,m,op=1; while(scanf("%d%d",&n,&m),n||m) { memset(head,-1,sizeof(head)); num=0; for(i=0;i<m;i++) { scanf("%d%d",&x,&y); addedge(x,y); addedge(y,x); } memset(dfs,-1,sizeof(dfs)); idx=ans=0; Tarjan(1,-1); memset(head,-1,sizeof(head)); nume=0; for(i=0;i<num;i++) { x=belong[E[i].st]; y=belong[E[i].ed]; if(x==y)continue; Addedge(x,y); Addedge(y,x); } memset(vis,0,sizeof(vis)); dfs[0]=0; low[0]=0; dfs1(0); memset(vis,0,sizeof(vis)); printf("Case %d:\n",op++); scanf("%d",&k); ans--; while(k--) { scanf("%d%d",&x,&y); Lca(belong[x],belong[y]); printf("%d\n",ans); } printf("\n"); } return 0; }