tarjan複習小結

2022-03-03 02:24:14 字數 1551 閱讀 6243

雖然是複習,但還是學到許多。

過程中遇到四種邊

1>樹枝邊:\(dfs\)搜尋樹上的邊 滿足邊\((u,v) ,v\)不在棧中 \(u\)為\(v\)的父節點

2>前向邊:與\(dfs\)方向一致 祖先指向子孫 沒什麼用

3>後向邊:與\(dfs\)方向相反 子孫指向祖先 滿足邊\((u,v)\). \(v\)在棧中,\(u\)為\(v\)的祖先節點

4>橫叉邊:從某個結點指向搜尋樹中另一子樹中某結點的邊 滿足邊\((u,v)\), \(v\)在棧中 \(u\)不為\(v\)的祖先節點

定義兩個陣列\(dfn\)和\(low\),\(dfn[x]\)表示\(x\)節點是第幾個被遍歷到的。\(low[x]\)表示\(x

x\)以及它的所有子樹的出邊的\(dfn\)的最小值,由定義可以得出:

如果\((u,v)\)是樹枝邊 \(low[u]=min(low[u],low[v])\)

如果是橫叉邊或後向邊 \(low[u]=min(dfn[v],low[u])\)

當結點\(u\)的搜尋過程結束之後,若\(dfn[u] == low[u]\) 則以\(u\)為根的搜尋子樹上所有還在棧中的結點,是乙個強連通分量,可退棧,為什麼呢????

我也不知道

通俗的說,若\(u\)為強連通分量的根,那麼它的子孫中的最高祖先應該是它本身。

陣列的初始化,當首次到達\(u\)這個點時,更新\(low\)與\(dfn\)的值, 將\(u\)入棧

更新\(low[u]\)

如果\((u,v)\)是樹枝邊 \(low[u]=min(low[u],low[v])\)

如果是橫叉邊或後向邊 \(low[u]=min(dfn[v],low[u])\)

如果u的子樹全被遍歷完,\(low[u] == dfn[u]\)那麼退棧,退到\(u\)退出,這些退出的元素就是乙個強連通分量。

void tarjan(int x) 

if (dfn[x] == low[x])

}}for (int i = 1; i <= n; i++)

if (!dfn[i]) tarjan(i);

其實就是縮點,要不然也沒別的用處。

因為每乙個強連通分量中的點都是相互可達的,我們可以將當前這個強連通分量縮成乙個點,這個點的權值由題目來定(通常會有強連通分量中的點權和或者點權的最小值)

我們用到染色的思想,因為退棧的時候退棧的所有元素都是同乙個強連通分量中的,所以我們可以在這個時將所有的點都染成同一種顏色,同時處理縮完點之後點的權值。

code

void tarjan(int x) 

if (dfn[x] == low[x]) }}

例題

間諜網路

穩定婚姻

訊息擴散

hxy燒情侶

受歡迎的牛

校園網最大半連通子圖

網路協議

訊息的傳遞

間諜網路

Tarjan 複習小結

一 割點。void tarjan r i,r rt else low i min low i dfn to k if i rt sum 1 ans i 1 注意 在不聯通圖中,應當 for r i 1 i n i if dfn i tarjan i,i 這樣才能保證全部求到,注意根節點.二 橋。vo...

tarjan複習筆記

tarjan求強連通分量 割點總體思想 遍歷每乙個結點並使用並查集記錄父子關係。tarjan 是一種dfs的思想。我們需要從根結點去遍歷這棵樹。當遍歷到某乙個結點 稱之為 x xx 時,你有以下幾點需要做的。將當前結點標記為已經訪問。遞迴遍歷所有它的子節點 稱之為 y yy 並在遞迴執行完後用並查集...

Tarjan專題總結複習

dfn x x 第一次被訪問的時間順序 時間戳 搜尋樹 每個節點只訪問一次,所有訪問過的邊 x,y 構成一棵搜尋樹 low x 定義為以下節點的時間戳的最小值 1.subtree x 中的節點。2.通過 1 條不在搜尋樹上的邊,能夠到達 subtree x 的節點。void tarjan int x...