tarjan(太監 塔揚 塔尖)演算法

2022-05-01 02:00:13 字數 1783 閱讀 2988

好吧,先說一下這個演算法的名字問題,我真的無語了對於這個演算法名字。

(自己去看鏈接吧)我也很腦殘,總之這個演算法名字很奇怪就是了。這名字真多啊!廢話不多說了,開始x生活。(好吧,上面的話都是zht寫的)

(自己去看鏈接吧)我也很無奈,總之這個演算法名字很奇怪就是了。這名字真多啊!廢話不多說了。

演算法思路

如果對原圖進行深度優先搜尋,由強連通分量定義可知,任何乙個強連通分量是原圖的dfs樹的子樹。那麼,只要確定每個強連通分量子樹的根,然後根據這些根從樹的最底層開始,乙個乙個的取出強連通分量即可。那麼剩下的問題就是如何確定強連通分量的根如何從最底層開始拿出強連通分量了。

對於確定強連通分量的根,在這裡維護兩個陣列,乙個是dfn[maxn]乙個是low[maxn],其中dfn[v]表示頂點v被訪問的時間,low[v]為頂點v鄰接的未刪除的頂點u的low[n]和low[v]的最小值(low[v]初始化為dfn[e])。這樣,在一次深度優先搜尋的回溯過程中,如果發現low[v]的最小值(low[v]初始化為dfn[v])。這樣,在一次深度優先搜尋的回溯過程中,如果發現low[v] == dfn[v],那麼當前頂點強連通分量的,而且他的根是當前頂點的祖宗,那麼存在包含當前頂點的到其祖宗的迴路,可知low[v]一定被更改為乙個比dfn[v]更小的值。

對於如何取出強連通分量,這個比較簡單,如果當前節點為乙個強連通分量的根,那麼他的強聯通分量一定是以該根為根節點的(剩下節點)子樹。在深度優先遍歷的時候維護乙個堆疊,每次訪問乙個新節點,就壓入堆疊。由於當前節點是這個強聯通分量中最先被壓入堆疊的,那麼在當前節點以後壓入堆疊的並仍在堆疊中的節點都屬於這個強連通分量。假設乙個節點在當前節點壓入堆疊以後壓入並且還存在,同時不屬於該強連通分量,那麼一定屬於另乙個強連通分量,但當前節點是其根的祖宗,那麼這個強連通分量應該在此之前已經被取出。

2.偽**

(1)找乙個沒有被訪問過的節點v;否則,演算法結束。

(2)初始化dfn[v]和low[v]。

對於v所有的鄰接頂點u;

①如果沒有訪問過,則轉到步驟(2),同時維護low[v]。

②如果訪問過,但沒有刪除,維護low[v]。

如果low[v] == dfn[v],那麼輸出相應的強連通分量。

3.**

1

const

int maxn = 110;2

intm;

3struct

nodeedge[maxn + 10];6

7int tarbfs(int k , int lay , int &scc_num)

16if(temp[edge[i].t] == 1) low[k] =min(low[k] , low[edge[i].t]);17}

18if(dfn[k] ==low[k])while(stack[m--] !=k);24}

25return0;

26}2728

int tarjan(int

n)37

return

scc_num;

38 }

tarjan

完事兒。

有個大佬說我的**醜,於是我就co了乙個好看的

1

void tarjan(intu)2

15else

if(ins[v]) low[u] =std::min(low[u], dfn[v]);16}

17if(low[u] ==dfn[u])

18while(v !=u);27}

28 }

好看的tarjan

完事兒。

漢諾塔(梵塔)問題

漢諾塔 梵塔 問題幾乎是所有的初學程式設計的人遇到的問題,這個問題很好的運用了遞迴的特性,將原來看起來不好解決的問題變得異常簡單,而且很容易理解。問題所有的人都知道就不描述了,很簡單且有注釋就不解釋了 include using namespace std int cnt 1 step計數 void...

漢諾塔問題(Hanoi塔)

1.將from柱最上面的movesum 1個圓盤移動到by柱 借助to柱 2.將from柱上剩下的那1個圓盤直接移動到to柱 3.將by柱上的movesum 1個圓盤移動到to柱 借助from柱 int sumofplates 4 總的盤子數目 int sum 3 初始時各柱子上盤子數目 enum ...

I 數塔(動態規劃)數塔問題

在講述dp演算法的時候,乙個經典的例子就是數塔問題,它是這樣描述的 有如下所示的數塔,要求從頂層走到底層,若每一步只能走到相鄰的結點,則經過的結點的數字之和最大是多少?已經告訴你了,這是個dp的題目,你能ac嗎?input 輸入資料首先包括乙個整數c,表示測試例項的個數,每個測試例項的第一行是乙個整...