tarjan算法的原理和實現

Tarjan算法的操作原理如下:

  1. 在任何深度優先搜索中,同一強連通分量內的所有頂點均在同一棵深度優先搜索樹中。也就是說,強連通分量一定是有向圖的某個深度搜樹子樹。
  2. 我們用low值記錄該點所在強連通子圖對應的搜索子樹的根節點的Dfn值。注意,該子樹中的元素在棧中一定是相鄰的,且根節點在棧中一定位於所有子樹元素的最下方。
  3. 強連通分量是由若干個環組成的。所以,當有環形成時(也就是搜索的下一個點已在棧中),我們將這一條路徑的low值統一,即這條路徑上的點屬於同一個強連通分量。
  4. 如果遍歷完整個搜索樹後某個點的dfn值等於low值,則它是該搜索子樹的根。這時,它以上(包括它自己)一直到棧頂的所有元素組成一個強連通分量。

low值和Dfn值各代表什麼:

Dfn值代表在一次深度優先搜索中各節點所處的次序,如果一個圖是強連通的,它必然是可以被一個環串起所有的點,反之則不然,所以葉子節點必然是存在的。

什麼樣的節點可以看成根節點:low[v]=Dfn[v]。這個根節點是強連通子圖的根節點。

== 僞代碼 ==
 '''algorithm''' tarjan '''is'''
   '''input:''' 圖 ''G'' = (''V'', ''E'')
   '''output:''' 以所在的強連通分量劃分的頂點集
 
   ''index'' := 0
   ''S'' := empty    ''// 置棧爲空''
   '''for each''' ''v'' '''in''' ''V'' '''do'''
     '''if''' (''v''.index is undefined)
       strongconnect(''v'')
     '''end if'''
 
   '''function''' strongconnect(''v'')
     ''// 將未使用的最小index值作爲結點v的index''
     ''v''.index := ''index''
     ''v''.lowlink := ''index''
     ''index'' := ''index'' + 1
     ''S''.push(''v'')
 
     ''// 考慮v的後繼結點''
     '''for each''' (''v'', ''w'') '''in''' ''E'' '''do'''
       '''if''' (''w''.index is undefined) '''then'''
         ''// 後繼結點w未訪問,遞歸調用''
         strongconnect(''w'')
         ''v''.lowlink := min(''v''.lowlink, ''w''.lowlink)
       '''else if''' (''w'' is in ''S'') '''then'''
         ''// w已在棧S中,亦即在當前強連通分量中''
         ''v''.lowlink := min(''v''.lowlink, ''w''.index)
       '''end if'''
 
     ''// 若v是根則出棧,並求得一個強連通分量''
     '''if''' (''v''.lowlink = ''v''.index) '''then'''
       start a new strongly connected component
       '''repeat'''
         ''w'' := ''S''.pop()
         add ''w'' to current strongly connected component
       '''until''' (''w'' = ''v'')
       output the current strongly connected component
     '''end if'''
   '''end function'''

變量<tt>index</tt>是深度優先搜索的結點計數器。<tt>S</tt>是棧,初始爲空,用於存儲已經訪問但未被判定屬於任一強連通分量的結點。注意這並非一個一般深度優先搜索的棧,結點不是在以它爲根的子樹搜索完成後出棧,而是在整個強連通分量被找到時。

最外層循環用於查找未訪問的結點,以保證所有結點最終都會被訪問。<tt>strongconnect</tt>進行一次深度優先搜索,並找到結點<tt>v</tt>的後繼結點構成的子圖中所有的強連通分量。

當一個結點完成遞歸時,若它的<tt>lowlink</tt>仍等於<tt>index</tt>,那麼它就是強連通分量的根。算法將在此結點之後入棧(包含此結點)且仍在棧中的結點出棧,並作爲一個強連通分量輸出。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章