Title
poj 3694 Network
Solution
可以用 T a r j a n Tarjan Tarjan求出图中的桥
注意有重边,
这里用的是朴素的方法。
对于 x , y x,y x,y,假如他们同在一个点里,对桥无减少的贡献,否则同时枚举到 l c a lca lca的路径,将桥标志为 f a l s e false false,并减少桥的数量
Code
#include
#include
#include
#define rep(i,x,y) for(register int i=x;i<=y;i++)
using namespace std;
const int N=1e5+15;
struct node{int x,y,z,next;}a[N*10];
int low[N],dfn[N],tot,n,m,Q,naa,head[N],f[N],cnt,cs,B[N];
bool b[N];
void tarjan(int x){
int y;
low[x]=dfn[x]=++naa; B[x]=1;
for(int i=head[x];~i;i=a[i].next)
if(a[i].z==0){
a[i].z=a[i^1].z=1;
y=a[i].y;
if (B[y]==0) {
f[y]=x; tarjan(y);
low[x]=min(low[x],low[y]);
if (dfn[x]<low[y]) cnt++,b[y]=1;
}
else if (B[y]==1) low[x]=min(dfn[y],low[x]);
}
B[x]=2;
}
void lca(int x,int y){
if (dfn[x]<dfn[y]) swap(x,y);
while (dfn[x]>dfn[y])
cnt-=b[x],b[x]=0,x=f[x];
while (x!=y)
cnt-=b[y],b[y]=0,y=f[y];
return;
}
void add(int x,int y){
a[tot]=(node){x,y,0,head[x]}; head[x]=tot; tot++;
}
int main(){
while (scanf("%d%d",&n,&m)==2){
if (n==0&&m==0) break;
int x,y;
tot=naa=cnt=0;
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(head,-1,sizeof(head));
memset(f,0,sizeof(f));
memset(b,0,sizeof(b));
memset(B,0,sizeof(B));
rep(i,1,m) scanf("%d%d",&x,&y),add(x,y),add(y,x);
f[1]=1;
/*rep(i,1,n) if (!dfn[i]) */ tarjan(1);
scanf("%d",&Q);
printf("Case %d:\n",++cs);
rep(i,1,Q){
scanf("%d%d",&x,&y);
lca(x,y);
printf("%d\n",cnt);
}
}
return 0;
}