【有向圖】強連通份量-Tarjan算法

很久沒寫博客了(都怪做業太多,絕對不是我玩的太嗨了算法

因此今天要寫的是一個高大上的東西:強連通spa

首先,是一些強連通相關的定義  //來自度娘3d

1.強連通圖(Strongly Connected Graph)是指在有向圖G中,若是對於每一對vi、vj,vi≠vj,從vi到vj和從vj到vi都存在路徑,則稱G是強連通圖。code

2.有向圖的極大強連通子圖,稱爲強連通份量(strongly connected components)。component

固然,看定義是確定看不懂的,因此,我舉個栗子說明一下blog

咱們如下圖爲例,這是一個特別經典的強連通圖,三個被框起來的地方就分別是三個強連通份量get

咱們DFS一下,從一出發,咱們從右至左遍歷,因此路徑即是1——>3——>5——>6,到了6,咱們發現無路可走了,就回到5,而6不能到達任何一個點,因此它獨自爲一個強連通份量。同理,5也是一個強連通份量。而1——>3——>4——>1——>2,能夠互相到達,因此這又是一個強連通份量。博客

 

Tarjan算法it

接下來,就是一個在強連通中,經常使用的一個算法。io

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

定義DFN(u)爲節點u搜索的次序編號(時間戳),Low(u)爲u或u的子樹可以追溯到的最先的棧中節點的次序號。

當DFN(u)=Low(u)時,以u爲根的搜索子樹上全部節點是一個強連通份量。

接下來演示一下算法:

從1開始DFS,把遍歷到的節點加入棧中。搜索到節點u=6時,DFN[6]=LOW[6],找到了一個強連通份量。退棧到u=v爲止,{6}爲一個強連通份量。

 返回到5,發現DFN[5]=LOW[5],退棧後{5}爲一個強連通份量。

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

 

因此,三個強連通份量所有都找出來了。

模板以下:

 1 void Tarjan(int u){
 2     dfn[u]=low[u]=++num;
 3     st[++top]=u;
 4     for (int i=fir[u]; i; i=nex[i]){
 5         int v=to[i];
 6         if (!dfn[v]){
 7             Tarjan(v);
 8             low[u]=min(low[u],low[v]);
 9         }
10         else if (!co[v])
11             low[u]=min(low[u],dfn[v]);
12     }
13     if (low[u] == dfn[u]){
14         co[u]=++col;
15         while (st[top]!=u){
16             co[st[top]]=col;
17             --top;
18         }
19         --top;
20     }
21 }
相關文章
相關標籤/搜索