tarjan演算法是一系列用dfs解決圖論問題的演算法,由美國計算機科學家tarjan提出。
首先先分析有向圖中tarjan演算法的應用:求有向圖強連通分量。
首先介紹一些在tarjan演算法中特殊陣列的定義,這個定義怎麼提出來的咱也不知道,咱也不敢問。
乙個是dfn陣列,表示dfs搜尋的時間戳,也就是第幾個搜尋到這個點。另乙個是low陣列,記錄的是某個點經過若干條樹邊和至多一條非樹邊到達的最小的dfn。
再說說什麼是非樹邊,樹邊。樹邊感性理解就是dfs會得到一棵dfs搜尋樹,然後這棵搜尋樹上的邊就是樹邊,對應的不在樹上的就是非樹邊。而非樹邊又分兩種,返祖邊和橫叉邊。好吧其實非樹邊具體是啥沒用2333。
那麼感性理解一下我們大致可以得到乙個式子:low[u] = min(low[v],low[u]),u表示當前節點,v表示這個節點能到的節點。顯然對於節點u,如果它的子節點v的low更小,換句話說v可以到達乙個dfn更小的點,那麼u同樣可以經過u,v之間的樹邊到達那個dfn更小的點。
那如果某個點經過一頓操作,最後low值和dfn值仍相等,說明這個點到不了之前的點了,那這個點就是乙個強連通分量的根。如果我們維護乙個棧,把每個搜到的點放進去,如果搜完發現乙個點low和dfn相等就把這個點以及棧裡在它上面的點彈出去。因為這個點上面的點都是這個點可以到的點,都屬於同乙個強連通分量。
好的演算法就結束了。
1 #include2 #include3 #include4 #include5 #include6 #include7有向圖縮點#define n 10010
8#define m 100010
9#define b printf("break\n");
10using
namespace
std;
11int head[n],nxt[m],to[m],val[n],in
[n];
12int
n,m,cnt;
13void add(int u,int
v)14
21void
reset()
2229
intdfn[n],low[n],tim;
30int
scc[n];
31bool
vis[n];
32 stacks;
33void tarjan(int
u)34
46else
if(vis[v])
4750}51
if(dfn[u] ==low[u])
5260
s.pop();
61 scc[u] =u;
62 vis[u] = 0;63
}64}65
intdis[n];
66int
topo_sort()
6776}77
while
(q.size())
7888}89
int ans = 0;90
for(int i = 1;i <= n;i++) ans =max(ans,dis[i]);
91return
ans;92}
93int
from
[m],tto[m];
94int
main()
95101
for(int i = 1;i <= m;i++)
102106
for(int i = 1;i <= n;i++)
107110
reset();
111for(int i = 1;i <= m;i++)
112118
}119 printf("%d"
,topo_sort());
120 }
tarjan演算法詳解
參考 tarjan演算法在強連通分量分離中運用很廣,書寫簡單,並且可以拓展到圖的割點,割邊上,十分強大 具體思路 令dfn u 表示當前點的時間戳 low u 表示當前點所能到達的點的時間戳中最小的乙個 到達點u時,將其入棧 拓展點u後代 當且僅當dfn u low u 時,棧頂元素全部出棧,此時出...
Tarjan 演算法筆記
tarjan演算法 tarjan演算法屬於圖論中的乙個演算法,主要用來求乙個圖中的強連通分量,之後就可以做很多事,比如說縮點 求雙聯通分支等。強連通 在乙個有向圖中,對於幾個點,如果它們能夠互相到達,那麼稱它們強連通。強連通分量 可以這樣理解 把乙個圖里的點分成幾坨,每坨中的點都能夠互相到達 他們強...
Tarjan演算法詳解
tarjan演算法的用途 1.求橋和割點 2.求點和邊的雙連通分量 3.求強連通 targan演算法的流程 利用dfs來遍歷圖來構建一種數型的結構 tarjan演算法的兩個核心陣列 1 對於第一種用途 tarjan演算法原理 我們從1開始遍歷,發現6,5,4的low不小於dfn 3 故3為割點 即4...