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,然后跑的时候,判断如果搜索完以后,这个点父亲的dfn值依然比自己low小,说明自己并没有再走到比父亲dfn还小的节点,也就是自己和自己父亲这条边就是割边了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#define MAXN 150010
#define REP(i,k,n) for(int i=k;i<=n;i++)
#define in(a) a=read()
using namespace std;
inline int read(){
int f=
1,x=
0;
char ch=
getchar();
for(;!isdigit(ch);ch=
getchar())
if(ch==
'-')
f=-
1;
for(;isdigit(ch);ch=
getchar())
x=x*
10+ch-
'0';
return x*
f;
}
int n,m,cnt,ans;
int dfn[MAXN],low[MAXN];
int total=
0,head[MAXN],nxt[MAXN<<
1],to[MAXN<<
1];
inline void adl(
int a,
int b){
total++
;
to[total]=
b;
nxt[total]=
head[a];
head[a]=
total;
return ;
}
inline void tarjan(
int u,
int f){
low[u]=dfn[u]=++
cnt;
for(
int e=head[u];e;e=
nxt[e]){
if(!dfn[to[e]] && to[e]!=
f){
tarjan(to[e],u);
low[u]=
min(low[to[e]],low[u]);
if(low[to[e]]>dfn[u]) ans++
;
}
else if(dfn[to[e]]<low[u] && to[e]!=f) low[u]=
dfn[to[e]];
}
return ;
}
int main(){
while(scanf(
"%d%d",&n,&m)!=
EOF){
if(n==
0 && m==
0)
return 0;
total=
0;
memset(dfn,0,
sizeof(dfn));
memset(low,0,
sizeof(low));
memset(head,0,
sizeof(head));
cnt=ans=
0;
int a,b;
REP(i,1,m){
in(a);
in(b);
adl(a,b);
adl(b,a);
}
tarjan(1,
0);
cout<<ans<<
endl;
}
}
转载于:https://www.cnblogs.com/jason2003/p/9702994.html
相关资源:JAVA上百实例源码以及开源项目