输出各个重连通分量的边

输出各个重联通分量的边

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <set>
#include <stack>
#include <map>
#include <climits>

using namespace std;

#define LL long long
const int INF=0x3f3f3f3f;

const int N = 10101;
int n,m;

struct Edge
{
    int u,v,next;
    Edge() {}
    Edge(int _u,int _v)
    {
        u=_u,v=_v,next=0;
    }
    int cmp(Edge &t)
    {
        return (u==t.u&&v==t.v)||(u==t.v&&v==t.u);
    }
    void print()
    {
        printf("%d->%d ",u,v);
    }
} edge[N<<4];
int s[N],cnt;
int dfn[N],low[N],dep;
bool vis[N];
bool gao[N][N];
stack<Edge>S;

void AddEdge(int u,int v)
{
    edge[cnt].u=u;
    edge[cnt].v=v;
    edge[cnt].next=s[u];
    s[u]=cnt++;
}

void tarjan(int u,int pre)
{
    dfn[u]=low[u]=++dep;
    vis[u]=true;
    for(int i=s[u];~i;i=edge[i].next)
    {
        int v=edge[i].v;
        if(v==pre||gao[v][u]||gao[u][v]) continue;
        gao[v][u]=gao[u][v]=true;//这里要注意标记边.回边也只能走一次.
        S.push(Edge(u,v));
        if(!vis[v])
        {
            tarjan(v,u);
            low[u]=min(low[u],low[v]);
        }
        else low[u]=min(low[u],dfn[v]);//回边
        if(low[v]>=dfn[u])//删除顶点U,子节点V所在的子树将脱离.
        {
            Edge t=Edge(u,v);
            while(1)
            {
                Edge t1=S.top();
                S.pop();
                t1.print();
                if(t1.cmp(t)) break;
            }
            printf("\n");
        }
    }
}

int main()
{
    scanf("%d%d",&n,&m);
    {
        memset(s,-1,sizeof s);
        cnt=0;
        for(int i=0; i<m; i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            AddEdge(u,v);
            AddEdge(v,u);
        }
        memset(vis,0,sizeof vis);
        memset(gao,0,sizeof gao);
        dep=0;
        tarjan(1,0);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值