tarjan演算法(強連通分量與割點)

2021-08-26 15:18:54 字數 2752 閱讀 1690

tarjan演算法可以求有向圖的割點割邊強連通分量(還有一些奇奇怪怪的操作)

我只會割點和強連通分量,割邊(和縮點)以後可能會加,如果是來看割邊的話,現在跑還來得及。。

(先來一張有向圖叭)

用這張圖,我們來解釋一些東西:

設在有向圖g中,gg為其子圖,u,v分別是g中的節點。

強連通:如果u可以到達v,v也可以到達u,那麼u,v強連通。(比如2可以到達9,9可以通過9—10—3—2到達2)

強連通圖:若g內各點都強連通,就說g是強連通圖。

強聯通分量:若gg是強連通圖,就說它是g的強連通分量。

割點:設割去點u,g斷成了多個圖,就說u是g的割點。(如1)

所有的tarjan演算法都要用到兩個陣列:

dfn:節點的dfs序;

low:該節點所在強連通分量中最小的dfn值,可以理解為團隊主。

首先要維護乙個棧,來記錄我們找過了哪些點。

然後遍歷u的兒子

設v是u的子節點。

如果v沒有走過,那麼先遍歷v的兒子

若v的團隊主比u的團隊主更高階(low[v]否則u不變。

如果v已經處理過了在棧裡了

若v比u更高階(dfn[v]否則u不變,坐等v加入團隊。

這一部分的**:

inline void tarjan(int x)

else if(v[e[i].y])

low[x]=min(low[x],dfn[e[i].y]);

}

當考慮完團隊劃分整合之後,我們如何確定有幾個團隊呢

如果dfn[x]==low[x],顯然,x就是某個團隊的團隊主

此時我們需要++cnt(cnt代表目前團隊編號),然後將x之後的數全部彈出棧,壓入事先準備好的vector中(怎麼覺得有點像做菜)。因為在x之後的點都是從x出發遍歷到的,這些點之中沒有可以改變low[x]的,顯然他們都歸順於x。

這一部分的**:

if(dfn[x]==low[x])while(x!=y);

}

講完了演算法,就可以愉快的來一道板子題了

牛的舞會

這個。。裸的掉牙了。

#include#include#include#include#include#define maxn 10005

#define maxm 50005

using namespace std;

int n,m,head[maxn],tot;

int dfn[maxn],low[maxn],num,st[maxn],ans,top,cnt;

bool v[maxn];

struct nodee[maxm];

inline void ad(int x,int y)

vectorscc[maxn];

inline void tarjan(int x)

else if(v[e[i].y])

low[x]=min(low[x],dfn[e[i].y]);

} if(dfn[x]==low[x])while(x!=y); }}

int main()

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

for(register int i=1;i<=cnt;i++)

printf("%d",ans);

}

(嗚哇總算寫完前半部分啦)

如果乙個點是根節點,有多個子樹,它肯定是個割點。

如果乙個點不是根節點,它存在乙個子樹,無法連線更高階的團隊主,那麼這個點就是割點。

(可以這樣想,割掉以後那棵子樹無法和其他點連線,必然會產生新的塊)

板子題

**

#include#include#include#include#include#define maxn 100005

#define maxm 100005

using namespace std;

int n,m;

int head[maxn],tot,root;

int dfn[maxn],low[maxn],num,ans;

bool cut[maxn];

struct nodee[maxn<<1];

inline void ad(int x,int y)

inline void tarjan(int x)

} else }}

int main()

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

for(register int i=1;i<=n;i++)if(cut[i])++ans;

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

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

return 0;

}

終於寫完了qwq

flag插地:這周學會割邊和縮點!

謝謝你可以看到這裡呀

希望對你有所幫助

有寫的不好或者不對的地方要及時指出來哦qwq

強連通分量Tarjan演算法

o v e 通常的tarjan寫法是有個dfn陣列跟乙個instack陣列,我精簡了下 把這兩個陣列都刪去了,用更簡便的寫法代替,也省了空間。int low maxn 記錄這棵樹能到達的最早祖先 其實不一定是最早,但不影響使用 int time 時間戳 int num 連通分量的個數 int bel...

強連通分量 tarjan演算法

強連通分量 tarjan演算法 有向圖強連通分量 在有向圖g中,如果兩個頂點間至少存在一條路徑,稱兩個頂點強連通 strongly connected 如果有向圖g的每兩個頂點都強連通,稱g是乙個強連通圖。非強連通圖有向圖的極大強連通子圖,稱為強連通分量 strongly connected com...

強連通分量 Tarjan演算法

有向圖強連通分量 在有向圖g中,如果兩個頂點vi,vj間 vi vj 有一條從vi到vj的有向路徑,同時還有一條從vj到vi的有向路徑,則稱兩個頂點強連通。如果有向圖g的每兩個頂點都強連通,稱g是乙個強連通圖。有向圖的極大強連通子圖,稱為強連通分量。tarjan 演算法是基於對圖優先搜素的演算法 每...