Tarjan 算法&模板

Tarjan 算法算法

一.算法簡介spa

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

 

咱們定義:component

若是兩個頂點能夠相互通達,則稱兩個頂點強連通(strongly connected)。若是有向圖G的每兩個頂點都強連通,稱G是一個強連通圖。有向圖的極大強連通子圖,稱爲強連通份量(strongly connected components)。blog

例如:在上圖中,{1 , 2 , 3 , 4 } , { 5 } ,  { 6 } 三個區域能夠相互連通,稱爲這個圖的強連通份量。it

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

再Tarjan算法中,有以下定義。class

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

LOW[ i ] : 爲i或i的子樹可以追溯到的最先的棧中節點的次序號im

當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 }

 

 

(完)

相關文章
相關標籤/搜索