Tarjan求強連通分量

2021-08-08 01:18:55 字數 1567 閱讀 7053

【強連通分量】:

有向圖強連通分量:

在有向圖g中,如果兩個頂點間至少存在一條路徑,稱兩個頂點強連通(strongly connected)。

如果有向圖g的每兩個頂點都強連通,則稱g是乙個強連通圖。

非強連通圖有向圖的極大強連通子圖,成為強連通分量(strongly connected components)。

直接根據定義,用雙向遍歷取交際的方法求強連通分量,時間複雜度為o(n^2+m)。更好的方法是kosaraju演算法或者tarjan演算法。

兩者的時間複雜度都是o(n+m)。本文介紹的是tarjan演算法。

tarjan演算法是基於對圖深度優先搜尋的演算法,每個強連通分量為搜尋樹中的一顆子樹。

搜尋時,把當前搜尋樹中未處理的節點加入乙個堆疊,回溯時可以盤對棧頂到棧中的節點是否為乙個強連通分量。

定義dfn(u)為節點u搜尋的次序編號(時間戳)。low(u)為u或者u的子樹能夠追溯到的最早的棧中的節點的次序號。

由定義可以得出:

low(u)= min ((u,v)為樹枝邊,u為v的父節點dfn(v),(u,v)為指向棧中節點的後向邊(非橫叉邊))

當dfn(u)=low(u)時,以u為根的搜尋子樹上所有節點是乙個強連通分量。

附**:

#include#include#include#include#define maxn 1010

using namespace std;

int n,m,c=1,top=1,d=1,s=0,ans=0;

int cstack[maxn],deep[maxn],low[maxn],head[maxn],colour[maxn],num[maxn];//deep陣列就是 時間戳dfn陣列,且用了陣列模擬的棧。。。

bool beque[maxn];

struct nodea[maxn*5];//前向星存圖

inline int read()

while(c>='0'&&c<='9')

return date*w;

}void add(int x,int y)

void work(int x)

else if(beque[t])

low[x]=min(low[x],deep[t]);

}if(low[x]>=deep[x])while(cstack[--top]!=x);

}}int main()

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

if(!deep[i])

work(i);

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

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

if(colour[i]==num[0])

ans++;

printf("%d\n",ans);//強連通分量中節點個數

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

if(colour[i]==num[0])

printf("%d ",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求強連通分量

tarjan求強連通分量 我們知道,在有向圖g中,如果任意兩個頂點都是連通的 所謂連通就是兩個頂點都能互相到達 那麼這個圖就是強連通圖。非強連通圖的極大強連通子圖,被稱為強連通分量。那麼什麼是極大強連通子圖呢?舉個例子幫助理解一下 例如下面圖一所示,其中子圖就是乙個極大強連通子圖,子圖也是乙個極大強...

Tarjan求強連通分量

強連通分量可以用tarjan求 比兩遍dfn大概快30 定義乙個棧 把點壓進去,然後根據自己所能到的點,求出能到達的dfn序最小的點 由此得到從此點到low點中的點 在棧中 可以成為乙個強連通分量 具體實現是當x點滿足dfn low時,將棧中的點全部彈出至x點 可以證明每個點最多被彈出1次,每條邊最...