BSOJ1393【曙光试题】旅游航道

Description

  SGOI旅游局在SG-III星团开设了旅游业务,每天有数以万计的地球人来这里观光,包括联合国秘书长,各国总统和SGOI总局局长等。旅游线路四通八达,每天都有总躲得载客太空飞船在星团的星球之间来往穿梭,他们保证了任意两个星球之间总是可以通过航道到达。但是,最近由于财政出现了困难,一些一些太空飞船也过于古老,又没有足够的资金购买新产品,所有只好取消一些航道。如果某一条航道的删除使得一些星球不能到达,纳闷这条航道是不能删除的,称之为“主要行道”。SGOI旅游局局长希望知道主要行道的数目,但是航道较多,他不能手工计算,于是,他委托你写一个程序,计算主要航道数目。

Input

  输入文件包含若干组数据。每组数据的首行有两个数m,n(1<=m<=15000,1<=n<=40000)。星球的编号从1到m。以下n行每行用两个整数a,b(1<=a,b<=m)描述一条航道的信息,表示从星球a到星球b是有航道的。数据有SGOI旅游局提供,你无需担心数据有错。输入文件以一行“0 0”为结束。

Output

  输出文件共有C行,第I行仅有一个数,表示第I组输入数据的主要行道数目。

Sample Input

2 1
1 2
0 0

Sample Output

1

分析

一道无向图求割边的裸题……

Tarjan后if(low[v]>dfn[u]),连接u和v的点即为割边。

注意判断if(father!=x),判断无向图中的重边。

PS:题目描述有错别字不要去管QwQ&&QAQ

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register long long
ll bj,h[15005],n,m,cnt,cntt,js,dfn[15005],low[15005],ans;
struct did{
	ll next,to;
}edge[100005];
inline ll read()
{
	re luoyang=0;
	char did=getchar();
	while(did<'0'||did>'9') did=getchar();
	while(did>='0'&&did<='9')
	luoyang=luoyang*10+did-'0',did=getchar();
	return luoyang;
}
inline void addedge(ll a,ll b)
{
	edge[++cnt].to=b;
	edge[cnt].next=h[a];
	h[a]=cnt;
}
inline void tarjan(ll x,ll father)
{
	dfn[x]=low[x]=cntt++;
	for(re i=h[x];i;i=edge[i].next)
	{
		if(dfn[edge[i].to]==-1)
		{
			tarjan(edge[i].to,x);
			low[x]=min(low[x],low[edge[i].to]);
			if(low[edge[i].to]>dfn[x])
			ans++;
		}
		else if(father!=edge[i].to)
		low[x]=min(low[x],dfn[edge[i].to]);
	}
}
int main()
{
	re n,m;
	while(scanf("%lld%lld",&n,&m))
	{
		if(n==0&&m==0)
		return 0;
		memset(dfn,-1,sizeof(dfn));
		memset(low,-1,sizeof(low));
		memset(h,0,sizeof(h));
		cnt=cntt=ans=0;
    	        for(re i=1;i<=m;i++)
		{
			re a=read(),b=read();
			addedge(a,b);addedge(b,a);	
		}
		tarjan(1,0);
		cout<<ans<<endl;
    }
}

猜你喜欢

转载自blog.csdn.net/disangan233/article/details/81012209