強連通分量

2021-07-16 14:39:20 字數 1535 閱讀 8910

強連通分量仍然是資訊學中的基礎內容,在圖論中和連通分量一樣都是相當重要的東西。而強連通分量型別的題不知為什麼出現頻率很高,比如縮環什麼的,考了好多次……

先定義強連通分量。同樣設有乙個有向圖g=

,同時其中有乙個子圖g′

= ,使得任意兩點i,

j∈v′

都能互相到達。這叫做連通分量。而強連通分量,就是g′

的最大化(當然,圖中有可能有多個孤立的強連通分量)。強連通分量,在某種意義上來說,就是乙個大環。

那麼怎麼求呢?

我們考慮從某一點開始dfs,如果某個子圖g′

= 是強連通分量,那麼這個強連通分量內部必定有至少一條邊從訪問較後的點連到訪問較前的點。換個說法,假設我們現在有一棵dfs樹,其中某棵子樹(這裡的「子樹」不是通常的子樹,這裡的「子樹」允許不完全包含通常子樹的某些節點)所對應的點集構成了強連通分量,那麼必然每個葉子節點都直接或間接地能到達這棵子樹的根節點,再換句話說,就是至少有乙個葉子節點向根節點直接連邊。

另外證明一樣東西:乙個強連通分量不可能不只是一棵子樹。用反證法,設有乙個強連通分量在dfs樹上佔兩棵子樹,然後容易看出,其中先訪問的那棵子樹的任意乙個節點都可以到達後訪問的那棵子樹的所有節點,於是,由dfs的演算法可知,dfs演算法如果要訪問那棵先訪問的子樹的對應子圖,那麼必然也會在這個訪問過程中訪問到另一棵子樹所對應的子圖(因為是dfs,「一條路走到黑」),再換句話說,就是後訪問的子樹必然要包含在先訪問的子樹裡,於是我們發現,它們其實是同一棵子樹,兩個的就證明完畢了,再用數學歸納法歸納一下,就都證出來啦。

好吧,說了這麼一大段,怎麼做呢?很簡單。這裡介紹tarjan演算法。tarjan演算法運用了時間戳的思想,若設pr

e(i)

為點i 第一次被訪問到的時間,而lo

w(i)

則是在dfs樹中以它為根結點的子樹(這次是通常的子樹了)中所有能夠訪問到的最前的點(即被訪問到的時間最早),那麼求起來就很容易了。如果我們記錄一下lo

w(i)

,往每個點上打個時間標記,那就大概是像這樣:

int nowt = 0;

int pre[maxn];

int low[maxn];

int dfs(int x)

於是,就像上面的那段**一樣,我們在dfs回來的時候再更新一遍lo

w(i)

,然後就做完了。

如果我們繼續用乙個棧來維護,比如說每訪問到乙個點就pu

sh()

進去,然後當dfs回來(即大概是**中(*)處)時遇到lo

w(i)

=pre

(x) 的點時,就意味著這個點是強連通分量中被首個訪問到的點,於是就一直將棧中元素彈出直到彈出了這乙個點為止,於是我們便已經彈出了乙個強連通分量了。

如果要縮環之類的,倒也不難,重建乙個新圖就好了。

其實強連通分量本也不難,難的是思路,求強連通分量的過程用到了時間戳,所以還是得好好掌握啊。

強連通分量 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 下圖中,子圖為乙個強連通分量,因為...