Tarjan 強連通分量學習筆記

2022-05-24 08:42:09 字數 1949 閱讀 6448

在乙個有向圖中,如果某兩點間都有互相到達的路徑,那麼稱中兩個點強連通,如果任意兩點都強連通,那麼稱這個圖為強連通圖;乙個有向圖的極大強連通子圖(不被原圖其它強連通子圖包含)稱為強連通分量

tarjan 演算法可以在 $o(n + m)$ 的時間內求出乙個圖的所有強連通分量。

若將有向圖的強連通分量都視作乙個點,則原圖會形成有向無環圖(dag)。

棧,dfs 樹中同一棵子樹中的點在棧中是相鄰的。

$\mathrm(u)$ 表示進入節點 $u$ 時的時間(時間截)。

$\mathrm(u)$ 表示由節點 $u$ 開始搜尋所能到達的點中,在搜尋樹上是 $u$ 的祖先且 $\mathrm$ 最小的節點的 $\mathrm$。

選定乙個節點作為根節點,開始 dfs;

初始化當前點的 $\mathrm$ 和 $\mathrm$ 均為當前時間截,並進棧;

遍歷當前點 $v$ 的所有鄰接點( $v$ 出邊連的點);

如果某個鄰接點 $u$ 在棧中,更新 $\mathrm(v) = \min(\mathrm(v), \mathrm(u))$;

如果某個鄰接點 $u$ 不在棧中,則對 $u$ 進行 dfs,完成後更新 $\mathrm(v) = \min(\mathrm(v), \mathrm(u))$;

$v$ 所有鄰接點都完成 dfs 後,如果滿足 $\mathrm(v) = \mathrm(v)$,則將棧中從 $v$ 到棧頂的所有元素出棧,並標記為乙個強連通分量。

如果某個鄰接點 $u$ 在棧中,更新 $\mathrm(v) = \min(\mathrm(v), \mathrm(u))$;

$u$ 已被訪問過且還未出棧,說明 $v$ 找到它的祖先 $u$,並形成了乙個環,此時要用 $u$ 去更新 $v$ 的最遠祖先。

如果某個鄰接點 $u$ 不在棧中,則對 $u$ 進行 dfs,完成後更新 $\mathrm(v) = \min(\mathrm(v), \mathrm(u))$;

點 $u$ 出發能到達的最遠祖先,點 $v$ 一定也能到達。

$v$ 所有鄰接點都完成 dfs 後,如果滿足 $\mathrm(v) = \mathrm(v)$,則將棧中從 $v$ 到棧頂的所有元素出棧,並標記為乙個強連通分量。

如果當前點 $v$ 為根的子樹下,無論怎麼走也無法到達 $v$ 的祖先,說明整棵子樹下的點組成乙個強連通分量。因為從 $v$ 進棧後,所有進棧的點都是子樹內的點,所以這個點在棧中的位置到棧頂位置中的點為同乙個強連通分量。

#include #include const int size = 100005;

int scc[size], scctot;

int st[size], top;

int low[size], dfn[size], time;

int h[size], to[size << 1], nxt[size << 1], tot;

int min(int x, int y)

void add(int x, int y)

void tarjan(int x) else if (!scc[y])

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

top--;

// x 出棧 }}

int main()

for (int i = 1; i <= n; i++) if (!dfn[i]) tarjan(i);

printf("%d\n", scctot);

for (int i = 1; i <= n; i++) printf("%d ", scc[i]);

return 0;

}

強連通分量 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

洛谷 p2812 校園網路 洛谷 p3387 縮點 include include include include include using namespace std struct arrbot 1100000 d 1100000 int head 20000 h 20000 stack 200...

強連通分量 tarjan

struct enodeedge maxm int p maxn ec void inserte int u,int v,int w int dfn maxn ctime,low maxn 時間戳,時間戳計數,祖先時間。int gid maxn gc 分量陣列,分量計數。bool ins maxn ...