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