Network(tarjan缩点建树,在LAC删割边)

/*
Network
POJ - 3694
https://vjudge.net/problem/POJ-3694
在无向图中动态添边,求割边个数
先tarjan缩点建树,在LAC删割边,不懂得画个图就明白了
*/
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
#define maxm 400010
#define maxn 100010
struct Edge{
	int v,next;
}edge[maxm];
int head[maxn];
int dfn[maxn],low[maxn];
int judge[maxn];
int pre[maxn];
int cnt,total,ans;
int n,m;
void add(int u,int v){
	edge[cnt].v=v;
	edge[cnt].next=head[u];
	head[u]=cnt++;
}
void init(){
	memset(judge,0,sizeof(judge));
	memset(head,-1,sizeof head);
	memset(dfn,0,sizeof dfn);
	memset(low,0,sizeof low);
	for(int i=1; i<=n; i++){
			pre[i]=i;
	}
	cnt=total=ans=0;
}
void tarjan(int u,int fa){
	dfn[u]=low[u]=++total;
	for(int i=head[u];~i;i=edge[i].next){
		int v=edge[i].v;
		if(!dfn[v]){
			pre[v]=u;
			tarjan(v,u);
			low[u]=min(low[u],low[v]);
			if(low[v]>dfn[u]){
				ans++;
				judge[v]=1;
			}
		}else if(fa!=v){
			low[u]=min(low[u],dfn[v]);
		}
	}
}
void lca(int u,int v){
	while(dfn[u]<dfn[v]){
		if(judge[v]){
			ans--;
			judge[v]=0;
		}
		v=pre[v];
	}
	while(dfn[u]>dfn[v]){
		if(judge[u]){
			ans--;
			judge[u]=0;
		}
		u=pre[u];
	}
	while(u!=v){
		if(judge[u]) ans--;
		if(judge[v]) ans--;
		judge[u]=0;
		judge[v]=0;
		u=pre[u];
		v=pre[v];
	}
}
int main(){
	int T=0;
	while(~scanf("%d %d", &n, &m)&&(n+m)){
		init();
		int u,v;
		for(int i=1;i<=m;i++){
			scanf("%d %d", &u, &v);
			add(u,v);
			add(v,u);
		}
		for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i,0);
		int t;
		printf("Case %d:\n",++T);
		scanf("%d", &t);
		while(t--){
			scanf("%d %d", &u, &v);
			lca(u,v);
			printf("%d\n", ans);
		}
		printf("\n");
	}
	return 0;
}


发布了70 篇原创文章 · 获赞 22 · 访问量 6474

猜你喜欢

转载自blog.csdn.net/weixin_44410512/article/details/104249846
今日推荐