#Tarjan+lca# [poj 3694] Network

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; 
}

你可能感兴趣的:(LCA问题(/tarjan),tarjan,lca,poj,3694,network)