双连通分量(DCC)

求双连通分量(tarjan方法)

解释都在代码里:

#include<iostream>
#include<cstdio>
#include<cstring>
#define CLR(a,b) memset(a,b,sizeof(a))
#define Min(a,b) a>b?b:a
using namespace std;
const int INF=1e5+5;
int dfn[INF];          //记录各结点的访问次序

int low[INF];          //low是追溯到DCC的根节点的dfn的值
                       //当根节点的某个直接儿子节点的low值大于或等于根节点的dfn的值时,
                       //就可以从栈中取值了,直到取到根节点为止时就是一个DCC  
int dcc_id[INF];      //存储各节点的所在的编号(就是你给他们编的号,从1到n)cnt_dcc就是编号下标!  
int stack[INF];       //栈:用深搜搜索节点并依次存储各个节点—以便于找到DCC
                      //即当发现环时就是一个DCC,用low标记的,从该栈中取值取到该根节点为止 
int father[INF];      //由于求DCC是在一个无向连通图中,即为双向的图
                      //该father就是为了防止某一节点又访问上一个节点(上一个节点搜出该节点)  
int top,cnt_dcc,cnt_idex;

struct Edge         //存储边的信息
{
    int to;
    Edge *next;
};

Edge *edge[INF];

void tarjan(int u)
{
    dfn[u]=low[u]=++cnt_index;
    stack[++top]=u;
    for(Edge *temp=edge[u];temp;temp=temp->next)
    {
        int v=temp->to;
        if(!dfn[v])
        {
            father[v]=u;
            tarjan(v);
            low[u]=Min(low[u],low[v]);    //更新low使每一个DCC中的low的值==根节点low值  
            if(low[v]>=low[u])           //当发现节点u的儿子节点v的low值>=dfn[u]  
            {                            //则就要取栈,即是时候取出DCC了
                cnt_dcc++;
                int j;
                do
                {
                    j=stack[top--];
                    dcc_id[j]=cnt_dcc;
                }while(v!=j);
                top++;                  //这里为什么要++?因为连着DCC是有共同节点的
            }
        }
        else if(v!=father[v])
            low[u]=Min(low[u],dfn[v]);
    }
}

void solve(int node)        //node 为要深搜的结点
{
    top=cnt_dcc=cnt_idex=0;
    CLR(dfn,0);
    tarjan(node);        //由于是无向连通图,只需深搜一个节点就都可以都到了  
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值