Tarjan 算法&模板


Tarjan 算法

一.算法簡介

Tarjan 算法一種由Robert Tarjan提出的求解有向圖強連通分量的算法,它能做到線性時間的復雜度。

 

我們定義:

如果兩個頂點可以相互通達,則稱兩個頂點強連通(strongly connected)。如果有向圖G的每兩個頂點都強連通,稱G是一個強連通圖。有向圖的極大強連通子圖,稱為強連通分量(strongly connected components)。

例如:在上圖中,{1 , 2 , 3 , 4 } , { 5 } ,  { 6 } 三個區域可以相互連通,稱為這個圖的強連通分量。

Tarjan算法是基於對圖深度優先搜索的算法,每個強連通分量為搜索樹中的一棵子樹。搜索時,把當前搜索樹中未處理的節點加入一個堆棧,回溯時可以判斷棧頂到棧中的節點是否為一個強連通分量。

再Tarjan算法中,有如下定義。

DFN[ i ] : 在DFS中該節點被搜索的次序(時間戳)

LOW[ i ] : 為i或i的子樹能夠追溯到的最早的棧中節點的次序號

當DFN[ i ]==LOW[ i ]時,為i或i的子樹可以構成一個強連通分量。

 

二.算法圖示

以1為Tarjan 算法的起始點,如圖

順次DFS搜到節點6

 回溯時發現LOW[ 5 ]==DFN[ 5 ] ,  LOW[ 6 ]==DFN[ 6 ] ,則{ 5 } , { 6 } 為兩個強連通分量。回溯至3節點,拓展節點4.

拓展節點1 , 發現1再棧中更新LOW[ 4 ],LOW[ 3 ] 的值為1

 回溯節點1,拓展節點2

自此,Tarjan Algorithm 結束,{1 , 2 , 3 , 4 } , { 5 } ,  { 6 } 為圖中的三個強連通分量。

不難發現,Tarjan Algorithm 的時間復雜度為O(E+V).

三.算法模板

 1 void Tarjan ( int x ) {
 2          dfn[ x ] = ++dfs_num ;
 3          low[ x ] = dfs_num ;
 4          vis [ x ] = true ;//是否在棧中
 5          stack [ ++top ] = x ;
 6          for ( int i=head[ x ] ; i!=0 ; i=e[i].next ){
 7                   int temp = e[ i ].to ;
 8                   if ( !dfn[ temp ] ){
 9                            Tarjan ( temp ) ;
10                            low[ x ] = gmin ( low[ x ] , low[ temp ] ) ;
11                  }
12                  else if ( vis[ temp ])low[ x ] = gmin ( low[ x ] , dfn[ temp ] ) ;
13          }
14          if ( dfn[ x ]==low[ x ] ) {//構成強連通分量
15                   vis[ x ] = false ;
16                   color[ x ] = ++col_num ;//染色
17                   while ( stack[ top ] != x ) {//清空
18                            color [stack[ top ]] = col_num ;
19                            vis [ stack[ top-- ] ] = false ;
20                  }
21                  top -- ;
22          }
23 }

 

 

(完)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM