一、定義
在有向圖G中,如果兩個頂點u,v間有一條從u到v的有向路徑,同時還有一條從v到u的有向路徑,則稱兩個頂點強連通。如果有向圖G的每兩個頂點都強連通,稱G是一個強連通圖。有向非強連通圖的極大強連通子圖,稱為強連通分量。

圖中,子圖{1,2,3,4}為一個強連通分量,因為頂點1,2,3,4兩兩可達。{5},{6}也分別是兩個強連通分量。
二、tarjan算法 時間復雜度是O(N+M)
四條邊:
樹枝邊:DFS時經過的邊,即DFS搜索樹上的邊。
前向邊:與DFS方向一致,從某個結點指向其某個子孫的邊。
后向邊:與DFS方向相反,從某個結點指向其某個祖先的邊。(返祖邊)
橫叉邊:從某個結點指向搜索樹中的另一子樹中的某結點的邊。
Tarjan算法是基於對圖深度優先搜索的算法,每個強連通分量為搜索樹中的一棵子樹。搜索時,把當前搜索樹中未處理的節點加入一個堆棧,回溯時可以判斷棧頂到棧中的節點是否為一個強連通分量。 定義DFN(u)為節點u搜索的次序編號(時間戳),Low(u)為u或u的子樹能夠追溯到的最早的棧中節點的次序號。 由定義可以得出,Low(u)=Min {Low(u), Low(v) } (u,v)為樹枝邊,u為v的父節點 . Low(u)=Min {Low(u), DFN(v) } DFN(v),(u,v)為指向棧中節點的后向邊(指向棧中結點的橫叉邊) } 當結點u搜索結束后,若DFN(u)=Low(u)時,則以u為根的搜索子樹上所有還在棧中的節點是一個強連通分量。
算法過程:
從節點1開始DFS,把遍歷到的節點加入棧中。搜索到節點u=6時,DFN[6]=LOW[6],找到了一個強連通分量。退棧到u=v為止,{6}為一個強連通分量。

初始化時Low[u]=DFN[u]=++index
返回節點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。

Low(u)=Min {Low(u), DFN(v) } DFN(v),(u,v)為指向棧中節點的后向邊
繼續回到節點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算法用途
1、有向圖的縮點
將同一個強連通分量中的點縮成同一個新結點,對於兩個新結點a,b之間有邊相連,當且僅當存在兩個點u屬於a,v屬於b。


2、求割點和橋
三、例題
「例 1」受歡迎的牛(信息學奧賽一本通 1513)
【題目描述】
原題來自:USACO 2003 Fall
每一頭牛的願望就是變成一頭最受歡迎的牛。現在有 N 頭牛,給你 M 對整數 (A,B),表示牛 A 認為牛 B 受歡迎。這種關系是具有傳遞性的,如果 A 認為 B 受歡迎,B 認為 C 受歡迎,那么牛 A 也認為牛 C 受歡迎。你的任務是求出有多少頭牛被除自己之外的所有牛認為是受歡迎的。
【輸入】
第一行兩個數 N,M;
接下來 M 行,每行兩個數 A,B,意思是 A 認為 B 是受歡迎的(給出的信息有可能重復,即有可能出現多個 A,B)。
【輸出】
輸出被除自己之外的所有牛認為是受歡迎的牛的數量。
【輸入樣例】
3 3
1 2
2 1
2 3
【輸出樣例】
1
【提示】
樣例說明
只有第三頭牛被除自己之外的所有牛認為是受歡迎的。
數據范圍:
對於全部數據,1≤N≤104,1≤M≤5×1041≤N≤104,1≤M≤5×104。


