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模板