Tarjan 算法学习笔记

无向图上的 Tarjan

定义:

  • dfnu:点 u 的时间戳,记录点 u 是 DFS 过程中被访问的时间。
  • lowu:记录点 u 经过至多一条非树边,所能达到的 dfn 最小的节点。

对于 DFS 中每一条遍历到的边 (u,v)

  • 若搜索树上 vu 的儿子,即边 (u,v) 是树边,则有 lowumin(lowu,lowv)
  • 否则边 (u,v) 一定是返祖边,即 vu 的祖先,则有 lowu=min(lowu,dfnv)
  • 可以发现对无向图进行 DFS 遍历时,是不可能存在横叉边的。

割点#

一个点是割点的充要条件是:

  • 若点 u 为搜索树的根,且 u 有两个以上的儿子,则 u 是割点。
  • 否则,如果存在 u 的一个儿子 v,满足 lowvdfnu,则 u 是割点。

点双连通分量#

  • DFS 过程中,用栈来存储被访问过的点。
  • 对于点 u,如果它的儿子 v 满足 lowvdfnu,则 u 是割点。不断弹栈,直到弹出 v;此时弹出的点和 u 就构成了一个点双。
  • DFS 结束后,栈中剩下的点们构成一个点双。
  • 割点会存在于多个点双之中,其他点以及每一条边只会存在一个点双里。

割边#

  • 首先非树边不可能成为割边。
  • 对于树边 (u,v),其中 uv 的父亲;如果 lowv>dfnu,则边 (u,v) 是割边。
  • 或者如果 lowu=dfnu,则 uu 的父亲之间的树边是割边。
  • 原理就是如果 v 无法通过返祖边和 u 的祖先联通,则 (u,v) 是割边。

边双连通分量#

  • 同样建立栈,将遍历到的点依次压入栈中。
  • 如果 lowu=dfnu,则 uu 的父亲是割边;则不断弹栈,直到弹出点 u。然后将这些刚弹出的点归入一个边双中。
  • 割边不会存在于任何一个边双里;其余边和所有点会恰好存在于一个边双里。
  • 容易发现,缩完点后的图会变成一棵优美的树。

有向图上的 Tarjan

定义:

  • dfnu:点 u 的时间戳,记录点 u 是 DFS 过程中被访问的时间。
  • lowu:记录点 u 经过至多一条返祖边,所能达到的 dfn 最小的节点。

强连通分量#

定义:

  • 如果两个点 u,v,存在 u 到 v 的路径,且存在 v 到 u 的路径,则称这两个点强连通。
  • 所有点都强连通的图称为强连通图。
  • 我们把图中极大的强连通子图称为强连通分量。

求法:

  • 同样开一个栈,将 dfs 到的点依次压入栈里面。
  • 每次更新 lowu 时,如果是横叉边且那个点无法回到 u 的某个祖先(即那个点不在栈里面)则无视。
  • dfnu=lowu 时,则不断弹栈,直到弹出 u,然后将这些点归入一个 SCC 中。
  • 缩完点后的图是个 DAG。
posted @   喵仔牛奶  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示
主题色彩