Tarjan(塔杨)算法详解

本文详细讲解了Tarjan算法,用于求解图的联通分量,包括有向图的强联通分量、点双联通分量和边双联通分量。通过教学代码和实例解析算法流程,帮助读者理解和实现该算法。
摘要由CSDN通过智能技术生成

前言

Tarjan(塔杨)算法其实不是很复杂,对于图这一块而言,Tarjan算法还是很有作用的,咱们现在一起来看看这个算法是啥东西以及咋实现。

简介

tarjan算法最直接的作用就是求图的联通分量。啥是联通分量呢?请你出去搞清楚再进来,谢谢。(啥是图?别进来了)
这算法如同基石一般,在此基础上我会研究联通分量的作用,后话了。
如果有人可以做个gif图,形象展示一下tarjan算法的过程,那就很棒了,可惜我不会。

教学代码-有向图的强联通分量

咱们先来个教学篇,讲一下这个tarjan算法的实现流程。
先给你一张单向图:
随便拷贝的
首先我得描述这些关系:

    vector<pair<int, int> >Relations;
    Relations.push_back(make_pair(1, 3));
    Relations.push_back(make_pair(1, 2));
    Relations.push_back(make_pair(2, 4));
    Relations.push_back(make_pair(3, 5));
    Relations.push_back(make_pair(3, 4));
    Relations.push_back(make_pair(4, 6));
    Relations.push_back(make_pair(5, 6));
    Relations.push_back(make_pair(4, 1));

接着看你喜欢了,我用邻接表保存这些单向关系

    vector<int> rel1, rel2, rel3, rel4, rel5, rel6;
    vector<int>* details[6] = {
   &rel1, &rel2, &rel3, &rel4, &rel5, &rel6};
    for (int i = 0; i < Relations.size(); ++i)
    {
   
        details[Relations[i].first-1]->push_back(Relations[i].second-1);
    }

然后我再定义几个要维护的数组还有一个stack

    int Vis[6] = {
    0 };     //0:not visited        1:in stack       2:leave stack
    int Dfn[6] = {
    0 };
    int Low[6] = {
    0 };
    int TimeStamp = 1;
    stack<int> sk;

这个Vis数组就有趣了,0表示没有访问过,1表示还在stack中,2表示已经出stack
timeStamp表示全局时间,没事可以暂时不理解。
Dfn数组用来记录每次的timeStamp
Low数组就没那么省心了。每个节点都或多或少有一片以自己为根节点的树。Low就代表了,这棵树能触碰到的最小的Dfn,加上dfs的帮助,于是这个Low就可以一直上传上去。
我相信你肯定已经懵逼了,毕竟这样说,太晦涩难懂。我这么说吧:啥叫强联通呢?从一个节点出发,兜兜转转,最后回到了自己。tarjan算法就是一种基于深度优先的算法,从起始节点一直找下去,最后找到了自己,那咋知道找到自己了呢?肯定是深度优先算法在回退的时候要一层层的将“哦吼,我找到最开始那个节点啦”这件事情带回去。
这样一来你就清楚了,tarjan算法对一个节点,要干点啥了:
tarjan:
1.先将Vis数组的下标置为已经访问,但是还没出stack(1),同时将Dfn和Low维护一下(就按照timeStamp走就行),顺便将这个节点入栈;
2.开始处理每一个自己的关系指向。
2.1如果这个关系指向是Vis=2,也就是早就经历过入栈出栈,那就别管了,pass
2.2如果这个关系指向是Vis=0,那就对其执行Tarjan算法(对没错,深度优先嘛,就递归了),反正执行完成后你总得出来(出来以后真的有可能也成2了,但是没关系,这个时候变2,那也是OK的,至少和自己有关系)。等出来之后,就直接借此更新Low下标,棒
2.3如果这个关系指向是Vis=1,也就是说,已经访问过了,那就没必要继续递归,直接借此更新Low下标,棒
3.深度,这事儿已经在第二步都做完了,下面咱们得开始退出了。这里退出的时候要伴随着可能发生的pop(每次pop出来的都是一组强联通分量)。像节点6走了一圈发现没啥,就要出去,很显然6是强联通分量,于是6pop出去了,同时更新一些Vis=2,开心。
轮到5了,显然和6一样的下场。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值