基礎-8:尋找強連通子圖

1 概述

所謂強連通子圖(一般是有向圖),就是在圖中存在某個子圖SG,對于SG中的任意兩個節點u,v,存在u -> ... -> v的路徑,也存在v-> ... -> u的路徑。強連通子圖應用十分廣泛,如社交網絡中的社區發現(如亞文化人群是一個相對閉環)、洗錢環節的賬戶閉環等,尋找強連通子圖是圖計算的一個重要應用。

2 算法

發現強連通子圖的著名算法包括Kosaraju算法Tarjan算法Gabow算法等,感興趣的童鞋可以深入閱讀。本文對尋找強連通子圖的思路進行分析。

下面以一個例子分析尋找強連通子圖的過程,如下圖1所示:


圖1:強連通子圖示例

顯然,(a,b,c,d)和(f,g,h,i)是兩個強連通子圖,如何找到這兩個連通子圖?肯定需要遍歷圖才可能發現。先看強連通子圖的規律,對于(a,b,c,d),不妨取第一個訪問的節點為a,當采用深度遍歷方法時,當訪問到c時,發現a是c的鄰接節點,即邊(c, a)是一條回邊,繼續深度遍歷到d節點時,發現a是d的鄰接節點,即(d, a)是一條回邊,回邊意味圖中存在環,即存在強連通子圖。

找到了強連通子圖的規律,剩下的就是如何實現了。從上一段的分析看出,通過深度遍歷的時候,可以發現回邊,從而發現強連通子圖。(深度遍歷過程請詳見前面的課程)深度遍歷在第一次發現節點v時,將其涂灰,當深度遍歷完v的所有鄰接節點時,將v涂黑。這里的關鍵是在對v進行深度遍歷時,如果發現v的子孫節點u,存在(u, v)這樣的邊,則存在回路;而且在深度遍歷時,當一個節點遍歷結束時,會回溯至其上層父節點root,繼續深度遍歷root的其它子節點。

這里,如果將深度遍歷進行適度改造,則容易發現其中的強連通子圖。基本思路:在深度遍歷v時,同時建立一個棧,當遍歷的過程中,根據鄰接邊,對相應的鄰接節點依照遍歷發現的順序入棧,可以發現規律。下面以(a,b,c,d,f)這個順序以此入棧,得到的結果如下圖2所示:


圖2: 棧示意圖

圖2中a'和a''示意存在回邊。當深度遍歷時,將所有的鄰接節點都加入到棧中,如發現某個節點已被涂灰,則說明存在回邊,將其與原節點區分,如圖2中的a'和a''。當節點遍歷完畢,回溯時,作出棧操作,如果出棧時,出現了<a'', ..., a>這樣的序列(注:a''和a指向的都是同一個節點),則其中必然存在強連通子圖,并且最大的<a'', ..., a>序列包含的元素才是尋找的強連通子圖,如圖2中(a,b,c,d)和(a, b, c)均是連通子圖,但是(a,b,c,d)才是要求的強連通子圖。

從上面的分析可以看出,尋找強連通子圖就是深度遍歷圖過程中的入棧出棧,并且在出棧序列中尋找首位相連的序列。

上面的分析與算法導論書中講解的求強連通子圖,其本質是一樣的,算法導論中利用的是轉置圖的再次遍歷,與本文中借助棧實際上是一致的。個人認為,本文中提到的方法更容易理解。

具體的算法實現,作一個簡單的概述:在深度遍歷時要申請一個棧,當一個節點訪問結束時,出棧并記錄出棧的歷史序列,如果存在首位相同的序列(可以借助hash記錄),則記錄此序列。遍歷完畢后,如果存在強連通子圖,必然會有一系列的強連通子圖序列,從中尋找最大子序列,即為返回結果。

3 小結

雖然本文分析了尋找強連通子圖的方法,但是,前文提及的三種算法:Kosaraju算法Tarjan算法Gabow算法也十分重要,在具體實踐中,直接調用這些成熟的算法更為有效。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 1 序 2016年6月25日夜,帝都,天下著大雨,拖著行李箱和同學在校門口照了最后一張合照,搬離寢室打車去了提前租...
    RichardJieChen閱讀 5,152評論 0 12
  • 第一章 緒論 什么是數據結構? 數據結構的定義:數據結構是相互之間存在一種或多種特定關系的數據元素的集合。 第二章...
    SeanCheney閱讀 5,807評論 0 19
  • https://zh.visualgo.net/graphds 淺談圖形結構https://zh.visualgo...
    狼之獨步閱讀 4,203評論 0 0
  • 數據結構與算法--圖論之尋找連通分量、強連通分量 尋找無向圖的連通分量 使用深度優先搜索可以很簡單地找出一幅圖的所...
    sunhaiyu閱讀 9,631評論 2 11
  • 《1%的可能性》2003年的電視劇,16年韓國又重新翻拍,不變的契約戀愛,不過新的演員,新的場景,情節,人物設定,...
    樂播報閱讀 658評論 0 1