点双连通分量的求解 Tarjan算法的拓展

问题描述:

给出一张连通的无向图  输出图中的所有连通分量




代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1050
using namespace std;
struct node{
    int from,to,next,vis;

    int equall(node b)
    {
        if((from==b.from)&&to==b.to||(from==b.to&&to==b.from))
            return 1;
        return 0;
    }
}edge[maxn*100],Edge;     //
int head[maxn];           //邻接表 
int e_num;               //


int dfn[maxn],low[maxn];
int num;


node stk[maxn*100];
int top;

int ss;

void init()
{
    memset(head,-1,sizeof(head));
    memset(dfn,0,sizeof(dfn));
    num=1;
    e_num=0;
    top=-1;
    ss=0;
}

void addedge(int a,int b)
{
    edge[e_num]={a,b,head[a],0};
    head[a]=e_num++;
    edge[e_num]={b,a,head[b],0};
    head[b]=e_num++;
}

void Tarjan(int u)
{
    dfn[u]=low[u]=num++;
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        if(!edge[i].vis)
        {
            edge[i].vis=edge[i^1].vis=1;        //防止回边(同一条边)重复入栈
            stk[++top]=edge[i];                 //压栈
            int v=edge[i].to;
            if(!dfn[v])
            {
                Tarjan(v);
                low[u]=min(low[u],low[v]);
                if(dfn[u]<=low[v])               //发现u是割点 -----构成一个连通分量
                {
                    printf("连通分量%d:\n",++ss);
                    while(1)
                    {
                        if(top<0)
                            break;
                        printf("%d-%d ",stk[top].from,stk[top].to);
                        top--;
                        if(edge[i].equall(stk[top+1]))
                            break;
                    }
                    cout<<endl;
                }
            }
            else low[u]=min(low[u],dfn[v]);
        }
    }
}

int main()
{
    int n,m;
    int a,b;
    while(1)
    {
        printf("请输入点数和边数:\n");
        scanf("%d%d",&n,&m);
        init();
        for(int i=1;i<=m;i++)
        {
            printf("请输入第%d条边:\n",i);
            scanf("%d%d",&a,&b);
            addedge(a,b);
        }
        Tarjan(1);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值