题目描述
给定一张图,请你输出桥的数量
输入(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;
}