有向圖強連通分量 Tarjan演算法【java實現】__演算法

來源:互聯網
上載者:User

註:本文章上部分內容轉載自http://www.cppblog.com/sosi/archive/2010/09/26/127797.html;一方面是網上有很多關於tarjan演算法的介紹,我覺得都沒有這個他的文章介紹的簡明易懂或者沒有具體的實現。另一方面,自己也順便用java實現了一下,所以發表出來和大家分享分享!


[有向圖強連通分量]

在有向圖G中,如果兩個頂點間至少存在一條路徑,稱兩個頂點強連通(strongly connected)。如果有向圖G的每兩個頂點都強連通,稱G是一個強連通圖。非強連通圖有向圖的極大強連通子圖,稱為強連通分量(strongly connected components)。

下圖中,子圖{1,2,3,4}為一個強連通分量,因為頂點1,2,3,4兩兩可達。{5},{6}也分別是兩個強連通分量。

[Tarjan演算法]

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

 

定義DFN(u)D記錄搜尋到該u的時間,也就是第幾個搜尋u的。Low(u)為u或u的子樹能夠追溯到的最早的棧中節點的序號。


演算法虛擬碼如下

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)

}


接下來是對演算法流程的示範。 從節點1開始DFS,把遍曆到的節點加入棧中。搜尋到節點u=6時,DFN[6]=LOW[6],找到了一個強連通分量。退棧到u=v為止,{6}為一個強連通分量。


返回節點5,發現DFN[5]=LOW[5],退棧後{5}為一個強連通分量。

返回節點3,繼續搜尋到節點4,把4加入堆棧。發現節點4向節點1有後向邊,節點1還在棧中,所以LOW[4]=1。節點6已經出棧,(4,6)是橫叉邊,返回3,(3,4)為樹枝邊,所以LOW[3]=LOW[4]=1。


繼續回到節點1,最後訪問節點2。訪問邊(2,4),4還在棧中,所以LOW[2]=DFN[4]=5。返回1後,發現DFN[1]=LOW[1],把棧中節點全部取出,組成一個連通分量{1,3,4,2}。


至此,演算法結束。經過該演算法,求出了圖中全部的三個強連通分量{1,3,4,2},{5},{6}。 可以發現,運行Tarjan演算法的過程中,每個頂點都被訪問了一次,且只進出了一次堆棧,每條邊也只被訪問了一次,所以該演算法的時間複雜度為O(N+M)。

演算法java實現如下:

Tarjan類:

import java.util.ArrayList;import java.util.Arrays;import java.util.List;import java.util.Stack;public class Tarjan {private int numOfNode;private List< ArrayList<Integer> > graph;//圖private List< ArrayList<Integer> > result;//儲存極大強連通圖private boolean[] inStack;//節點是否在棧內,因為在stack中尋找一個節點不方便。這種方式尋找快private Stack<Integer> stack;private int[] dfn;private int[] low;private int time;//public Tarjan(List< ArrayList<Integer> > graph,int numOfNode){this.graph = graph;this.numOfNode = numOfNode;this.inStack = new boolean[numOfNode];this.stack = new Stack<Integer>();dfn = new int[numOfNode];low = new int[numOfNode];Arrays.fill(dfn, -1);//將dfn所有元素都置為-1,其中dfn[i]=-1代表i還有沒被訪問過。Arrays.fill(low, -1);result = new ArrayList<ArrayList<Integer>>();}public List< ArrayList<Integer> > run(){for(int i=0;i<numOfNode;i++){if(dfn[i]==-1){tarjan(i);}}return result;}public void tarjan(int current){dfn[current]=low[current]=time++;inStack[current]=true;stack.push(current);for(int i=0;i<graph.get(current).size();i++){int next = graph.get(current).get(i);if(dfn[next]==-1){//-1代表沒有被訪問tarjan(next);low[current]=Math.min(low[current], low[next]);}else if(inStack[next]){low[current]=Math.min(low[current], dfn[next]);}}if(low[current]==dfn[current]){ArrayList<Integer> temp =new ArrayList<Integer>();int j = -1;while(current!=j){j = stack.pop();inStack[j]=false;temp.add(j);}result.add(temp);}}}
測試類別:

import java.util.ArrayList;import java.util.List;import java.util.Stack;public class Main {public static void main(String[] args) {                //建立圖int numOfNode = 6;List< ArrayList<Integer> > graph = new ArrayList<ArrayList<Integer>>();for(int i=0;i<numOfNode;i++){graph.add(new ArrayList<Integer>());}graph.get(0).add(1);graph.get(0).add(2);graph.get(1).add(3);graph.get(2).add(3);graph.get(2).add(4);graph.get(3).add(0);graph.get(3).add(5);graph.get(4).add(5);//調用Tarjan演算法求極大連通子圖Tarjan t = new Tarjan(graph, numOfNode);List< ArrayList<Integer> > result = t.run();                //列印結果for(int i=0;i<result.size();i++){for(int j=0;j<result.get(i).size();j++){System.out.print(result.get(i).get(j)+" ");}System.out.println();}}}


相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.