给一个联通的图,然后依次添加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;
}