桥的模板

题目描述

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

输入\(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\n",ans);
}
int main()
{
    scanf("%d%d",&n,&m);
    while(n||m)
    {
        init();
        solve();
        scanf("%d%d",&n,&m);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Lance1ot/p/9235657.html