Tarjan算法学习笔记

有向图强联通分量的tarjan算法 链接:https://www.byvoid.com/blog/scc-tarjan/
 
从上面的链接引用一段比较直观的伪码,描述tarjan算法的过程
tarjan(u)
{
    DFN[u]=Low[u]=++Index                      // 为节点u设定次序编号和Low初值
    Stack.push(u)                              // 将节点u压入栈中
    for each (u, v) in E                       // 枚举每一条边
        if (v is not visted)               // 如果节点v未被访问过
            tarjan(v)                  // 继续向下找
            Low[u] = min(Low[u], Low[v])
        else if (v in S)                   // 如果节点v还在栈内
            Low[u] = min(Low[u], DFN[v])
    if (DFN[u] == Low[u])                      // 如果节点u是强连通分量的根
        repeat
            v = S.pop                  // 将v退栈,为该强连通分量中一个顶点
            print v
        until (u== v)
}

 

简述一下我对几个重要概念的理解
DFN[u]:是一个“时间戳”,记录这个是第几个被访问的点
Low[u]:是指u能够去往的(追溯到)最早(时间戳最小)的点的时间戳值,若无更早则为DFN[u]
后向边(非横叉边):去点在栈内的边
横叉边:去点已访问过但已被弹出(此时不在栈内),通俗一点理解就是这条边不再“生成树”内
树枝边:去点未访问过(当然也不在栈内)
 
然后是几个判据
1.u是割点需满足下列其中一个条件
  (1)u为树根,且u有多于一个子树
  (2)u不为树根,且存在一条树枝边(u, v)使得DFN(u) < Low(v)
2.(u, v)是桥
  当且仅当 DFN(u) < Low(v)
 
链接中还给出了一个非常直观的例子,这里不再引用,具体请戳本文开头链接
 
 
最后附上相关的kuangbin模板


posted @ 2015-05-20 16:58  地鼠地鼠  阅读(230)  评论(0编辑  收藏  举报