桥的模板

题目描述

给定一张图,请你输出桥的数量

输入(and)输出格式

输入

输入包含多组数据,每行有两个元素(n,m),表示图中有(n)个节点,(m)条边

接下来有(m)行每行两个数,表示这两个点有边相连。

结束时,(n,m)都为(0)

输出

共一个数字,为桥的个数。并换行

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int n,m;
const int maxn=15100;
struct node
{
	int point;
	int nxt;
	int opposite;
};
int head[maxn<<1],tail,t;
int dfn[maxn<<1],low[maxn<<1];
bool bri[maxn<<2],vis[maxn<<2];
node line[maxn<<2];
void add(int a,int b)
{
	line[++tail].point=b;
	line[tail].nxt=head[a];
	line[tail].opposite=tail+1;
	head[a]=tail;
	line[++tail].point=a;
	line[tail].nxt=head[b];
	head[b]=tail;
	line[tail].opposite=tail-1;
}
void init()
{
	memset(head,0,sizeof(head));
	memset(dfn,0,sizeof(dfn));
	memset(low,0,sizeof(low));
	memset(bri,false,sizeof(bri));
	memset(vis,false,sizeof(vis));
	tail=0;
	t=0;return ;
}
void tarjan(int now)
{
	dfn[now]=low[now]=++t;
	for(int i=head[now];i;i=line[i].nxt)
		if(!vis[line[i].opposite])
		{
			vis[i]=true;
			int nxt=line[i].point;
			if(!dfn[nxt])
			{
				tarjan(nxt);
				low[now]=min(low[now],low[nxt]);
				if(low[nxt]>dfn[now])
					bri[i]=bri[line[i].opposite]=true;
			}
			else	low[now]=min(low[now],dfn[nxt]);
		}
		else	vis[i]=true;
}
void solve()
{
	int a,b;
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&a,&b);
		add(a,b);
	}
	for(int i=1;i<=n;i++)
		if(!dfn[i])
			tarjan(i);
	int ans=0;
	for(int i=1;i<=(m<<1);i++)
		if(bri[i])	ans+=1;
	ans>>=1;
	printf("%d
",ans);
}
int main()
{
	scanf("%d%d",&n,&m);
	while(n||m)
	{
		init();
		solve();
		scanf("%d%d",&n,&m);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/Lance1ot/p/9235657.html