给一个联通的图,然后依次添加Q条边,每次添加边之后,图中还剩多少条桥?先求一下边双联通重构成一棵树,然后就是求LCA了,查询的时候从两个点开始往祖先一边爬一边标记掉沿途的边,根据每次标记掉的点以及上一次的答案就可以递推出当前的答案...切记一点这题有重边...所以求ebc的时候记得用边判父节点...思路不是很难,但代码写起来太坑爹了......
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <cstring> #include <vector> #include <stack> using namespace std; typedef long long ll; const int maxn=155000; struct EDGE { int v,w,next; }ed1[maxn<<2],ed2[maxn<<2],ed3[4040]; int g[maxn]; int gg[maxn]; int qe[maxn]; int p1,p2,p3; stack<int> s; int pre[maxn]; int id[maxn],dfs_clock,ebc_cnt; int deg[maxn]; bool ok[maxn]; int n,m,k,p,q; int dfs(int u,int frm) { int lowu=pre[u]=++dfs_clock; s.push(u); for (int j=g[u];j!=-1; j=ed1[j].next) { int v=ed1[j].v; if (j==(frm^1)) continue; if (!pre[v]) { int lowv=dfs(v,j); lowu=min(lowu,lowv); } else if (pre[v]<pre[u]) { lowu=min(lowu,pre[v]); } } if (lowu==pre[u]) { ebc_cnt++; while (true) { int x=s.top(); s.pop(); id[x]=ebc_cnt; if (x==u) break; } } return lowu; } void findebc(int n) { memset(pre,0,sizeof pre); memset(id,0,sizeof id); while(!s.empty()) s.pop(); for (int i=1; i<=n; i++) { if (!pre[i]) dfs(i,-1); } } int dis[maxn]; bool vis[maxn]; int fa[maxn]; int res[maxn][3]; int fr[maxn]; int find(int x) { if (x==fa[x]) return fa[x]; return fa[x]=find(fa[x]); } void lca(int u) { vis[u]=true; fa[u]=u; int v; for (int j=qe[u]; j!=-1; j=ed3[j].next) { v=ed3[j].v; if (vis[v]) { res[ed3[j].w][2]=find(v); } } for (int j=gg[u]; j!=-1; j=ed2[j].next) { v=ed2[j].v; if (!vis[v]) { fr[v]=u; dis[v]=dis[u]+1; lca(v); fa[v]=u; } } } int ans[maxn]; int main() { // freopen("in.txt","r",stdin); int x,y; int cp=0; while(~scanf("%d%d",&n,&m)) { if (n==0 && m==0) break; cp++; printf("Case %d:\n",cp); memset(g,-1,sizeof g); memset(gg,-1,sizeof gg); memset(qe,-1,sizeof qe); p1=p2=p3=0; for (int i=1; i<=m; i++) { scanf("%d%d",&x,&y); ed1[p1].v=y; ed1[p1].w=1; ed1[p1].next=g[x]; g[x]=p1; p1++; ed1[p1].v=x; ed1[p1].w=1; ed1[p1].next=g[y]; g[y]=p1; p1++; } ebc_cnt=0; findebc(n); for (int i=1; i<=n; i++) for (int j=g[i]; j!=-1; j=ed1[j].next) { x=id[i]; y=id[ed1[j].v]; if (x!=y) { ed2[p2].v=y; ed2[p2].w=1; ed2[p2].next=gg[x]; gg[x]=p2; p2++; ed2[p2].v=x; ed2[p2].w=1; ed2[p2].next=gg[y]; gg[y]=p2; p2++; } } int sum=ebc_cnt-1; memset(vis,false,sizeof vis); memset(res,0,sizeof res); scanf("%d",&q); for (int i=1; i<=q; i++) { scanf("%d%d",&x,&y); x=id[x]; y=id[y]; ed3[p3].v=y; ed3[p3].w=i; ed3[p3].next=qe[x]; qe[x]=p3; p3++; ed3[p3].v=x; ed3[p3].w=i; ed3[p3].next=qe[y]; qe[y]=p3; p3++; res[i][0]=x; res[i][1]=y; } dis[0]=0; lca(1); memset(ans,0,sizeof ans); memset(ok,false,sizeof ok); ans[0]=sum; for (int i=1; i<=q; i++) { x=res[i][0]; y=res[i][1]; int t=res[i][2]; ans[i]=ans[i-1]; while (x!=t) { if (!ok[x]) ans[i]--,ok[x]=true; x=fr[x]; } while (y!=t) { if (!ok[y]) ans[i]--,ok[y]=true; y=fr[y]; } } for (int i=1; i<=q; i++) printf("%d\n",ans[i]); printf("\n"); } return 0; }