tarjan基於這樣乙個定理:
在任何深度優先搜尋中,同一強連通支內的所有頂點均在同一棵深度優先樹中。也就是說,強連通分量一定是有向圖的某個深搜樹子樹。
證明:
在強連通支內的所有結點中,設r第乙個被發現。因為r是第乙個被發現,所以發現r時強連通支內的其他結點都為白色。在強連通支內從r到每一其他結點均有通路,因為這些通路都沒有離開該強連通支(據引理1),所以其上所有結點均為白色(未染色,未訪問)。因此根據白色路徑定理,在深度優先樹中,強連通支內的每乙個結點都是結點r的後代。
引理:白色路徑定理:
在乙個有向或無向圖g=(v,e)的深度優先森林中,結點v是結點u的後代當且僅當在搜尋發現u的時刻d[u],從結點u出發經一條僅由白色結點組成的路徑可達v。
證明:
→:假設v是u的後裔,w是深度優先樹中u和v之間的通路上的任意結點,則w必然是u的後裔,由推論1 u的發現時刻d[u]一定比w的發現時刻早,因此在時刻d[u],w應為白色(未發現)。
←:設在時刻d[u],從u到v有一條僅由白色結點組成的通路,但在深度優先樹中v還沒有成為u的後裔。不失一般性,我們假定該通路上的其他頂點都是u的後裔(否則可設v是該通路中最接近u的結點,且不為u的後裔),設w為該通路上v的祖先,使w是u的後裔(實際上w和u可以是同乙個結點)。根據推論1得f[w]≤f[u],因為v∈adj[w],對dfs_visit(w)的呼叫保證完成w之前先完成v,因此f[v]引理:推論1 後裔區間的嵌入
在有向或無向圖g的深度優先森林中,結節v是結點u的後裔當且僅當d[u](上述定理中,d[u]表示深搜過程中發現頂點的時間,f[u]表示對其深搜完畢的時間)
---------------
關於搜尋樹中的邊
對有向圖進行dfs, 得到深搜樹,與無向圖不同,無向圖只包括 樹邊和回退邊,而有向圖的樹包括四種:
若 dfn[v] < dfn[w] , (v,w) 是向前邊或者樹邊。
若 dfn[v] > dfn[w] , (v,w) 是回退邊或橫跨邊。
區分樹邊和向前邊: visiteid[v] = true, visited[w] = false, (v,w)為樹邊。
visited[v] = true, visited[w] = true, 且 dfn[v] < dfn[w], (v,w)為向前邊。
區分回退邊和橫邊:
(資料結構書上的). 搜尋過程中,每當樹邊(v,w)歸入樹邊集時,記下j 的父親 father[w] = v. 於是當遇上任意條邊(v,w), 當visited[v] = true, visited[w] = true, 且dfn[v] > dfn[w] ,就由節點v 沿著樹邊根據father陣列向上查詢w, 如果找到了w, 說明是回退邊,否則是橫邊。
橫邊有兩種,一種是森林各個樹之間的。一種是連通分量之內的。 當遇到橫跨邊,如果邊的頂點還未歸於乙個被搜尋完成的強連通分量, 那麼該橫邊的點是可達的。否則是不可達的,即該邊的頂點不可用。
tarjan 演算法原理:
既然強連通分量是深搜樹的一棵子樹,要找到乙個分量,只要找到樹根( 連線不同分量的橋的前端頂點) ,然後取出其所屬分量的頂點即可。
當深搜過程中遇到乙個分量,首先發現的頂點v肯定是樹根,由於分量是一棵子樹,且分量間頂點可互達,那麼其他頂點肯定能由v 發起的路徑到達,那麼其他節點都是v的子孫。
同無向圖雙連通分量的解決方式類似,我們定義 low 陣列,low[v] 表示,從v出發經過v 的子孫形成的路徑和一條回退邊,能夠到達的最淺層次的頂點的編號。注意這裡到達的頂點必須是可用的,我們說當乙個分量完成,其包括的頂點全部設定為不可用。其實如果邊是一條不同子樹之間的橫跨邊,它到達的頂點肯定是不可用的,因為那個點已經屬於另乙個分量。
在乙個分量中,樹根的子孫都不可能到達樹根的祖先頂點。(容易證明:如果跟是u,某子孫v可達u的祖先w,由於w->u->v->w, 則w也屬於該分量,且w應該是樹根,矛盾)
在dfs過程中,遇到新點令其dfn[u] = low[u] = 編號. 回溯時,如果發現dfn[u] == low[u], 則是分量子樹的樹根。 這是乙個充要條件。 -->: 如果u 是樹根,且由於是強分量,其子孫都可達到u, 則子孫的low 都是u 的編號。則low[u] = dfn[u]. <--: 如果low[u] == dfn[u], 假設u不是樹根,那麼肯定有u的祖先是樹根,那麼low[u]肯定比當前值小,矛盾,因此u是樹根。
如何取出分量? 我們遇到新頂點時將頂點入棧,在回溯時發現了根,且根是先被壓入棧的,那麼在根之後壓入的頂點都是分量中的頂點,否則如果有頂點屬於其他分量,就出現矛盾,因為在那個分量完成時,這個頂點已經彈出不可用了。
強連通分量 tarjan求強連通分量
雙dfs方法就是正dfs掃一遍,然後將邊反向dfs掃一遍。挑戰程式設計 上有說明。雙dfs 1 include 2 include 3 include 4 include 5 6using namespace std 7const int maxn 1e4 5 8 vector g maxn 圖的鄰...
強連通分量
對於有向圖的乙個頂點集,如果從這個頂點集的任何一點出發都可以到達該頂點集的其餘各個頂點,那麼該頂點集稱為該有向圖的乙個強連通分量。有向連通圖的全部頂點組成乙個強連通分量。我們可以利用tarjan演算法求強連通分量。define n 1000 struct edge e 100000 int ec,p...
強連通分量
在有向圖g中,如果兩個頂點間至少存在一條路徑,稱兩個頂點強連通 strongly connected 如果有向圖g的每兩個頂點都強連通,稱g是乙個強連通圖。非強連通圖有向圖的極大強連通子圖,稱為強連通分量 strongly connected components 下圖中,子圖為乙個強連通分量,因為...