OI Tarjin演算法整理

2021-07-26 11:43:44 字數 3409 閱讀 8170

其實,tarjan演算法的基礎是dfs。我們準備兩個陣列low和dfn。low陣列是乙個標記陣列,記錄該點所在的強連通子圖所在搜尋子樹的根節點的dfn值(很繞嘴,往下看你就會明白),dfn陣列記錄搜尋到該點的時間,也就是第幾個搜尋這個點的。根據以下幾條規則,經過搜尋遍歷該圖(無需回溯)和對棧的操作,我們就可以得到該有向圖的強連通分量。

陣列的初始化:當首次搜尋到點p時,dfn與low陣列的值都為到該點的時間。

堆疊:每搜尋到乙個點,將它壓入棧頂。

當點p有與點p』相連時,如果此時(時間為dfn[p]時)p』不在棧中,p的low值為兩點的low值中較小的乙個。

當點p有與點p』相連時,如果此時(時間為dfn[p]時)p』在棧中,p的low值為p的low值和p』的dfn值中較小的乙個。

每當搜尋到乙個點經過以上操作後(也就是子樹已經全部遍歷)的low值等於dfn值,則將它以及在它之上的元素彈出棧。這些出棧的元素組成乙個強連通分量。

由於每個頂點只訪問過一次,每條邊也只訪問過一次,我們就可以在o(n+m)的時間內求出有向圖的強連通分量。但是,這麼做的原因是什麼呢?

tarjan演算法的操作原理如下:

tarjan演算法基於定理:在任何深度優先搜尋中,同一強連通分量內的所有頂點均在同一棵深度優先搜尋樹中。也就是說,強連通分量一定是有向圖的某個深搜樹子樹。

可以證明,當乙個點既是強連通子圖ⅰ中的點,又是強連通子圖ⅱ中的點,則它是強連通子圖ⅰ∪ⅱ中的點。

這樣,我們用low值記錄該點所在強連通子圖對應的搜尋子樹的根節點的dfn值。注意,該子樹中的元素在棧中一定是相鄰的,且根節點在棧中一定位於所有子樹元素的最下方。

強連通分量是由若干個環組成的。所以,當有環形成時(也就是搜尋的下乙個點已在棧中),我們將這一條路徑的low值統一,即這條路徑上的點屬於同乙個強連通分量。

如果遍歷完整個搜尋樹後某個點的dfn值等於low值,則它是該搜尋子樹的根。這時,它以上(包括它自己)一直到棧頂的所有元素組成乙個強連通分量。

具體演算法演示下圖所示:

**實現: 1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

#include

#include

#define maxn 100000

struct

edgee[

maxn+1

];typedef

intarr

[maxn+1

];arr

head

,nxt

,stack

,dfn

,low;

bool

instack

[maxn+1

];int

tot,

index

,top

,cnum;

std::vector

<

int>

cset

[maxn+1

];//存強連通量

inline

void

link

(int

from

,intto)

; nxt[

tot]

=head

[from];

head

[from]=

tot;

}inline

intmin

(inta,

intb)

void

tarjan

(intu)

elseif(

instack[v

])}

if(dfn[u]

==low[u

])while(u

!=v&&top

>0)

; }

}int

main()

//for(int i=1;i<=ulimit;i++)

printf

("}");

} //printf("}");};

return0;

}they said "admonish your friends in private, praise them in public."

A 演算法 整理

a 演算法 目錄2.總結 注 本文引自 概念 a 探路搜尋,是指在有障礙物的時候,尋找到達目的地最短路徑的搜尋。先介紹一些前置知識助於自己理解a 啟發式搜尋 這是對每乙個搜尋位置進行評估,得到好的位置,再從這個位置進行搜尋直到目標。這樣子好處是 剪枝,效率更高。啟發式搜尋的關鍵是如何進行估價。估價函...

排序演算法整理

template void cinsertsort mysort function compare template void cselectsort mysort function compare swap datas i datas id void cshellsort mysort funct...

程式設計演算法整理

演算法一 快速排序演算法 快速排序是由東尼 霍爾所發展的一種排序演算法。在平均狀況下,排序 n 個專案要 n log n 次比較。在最壞狀況下則需要 n2 次比較,但這種狀況並不常見。事實上,快速排序通常明顯比其他 n log n 演算法更快,因為它的內部迴圈 inner loop 可以在大部分的架...