Tarjan演算法(強連通分量分解)
如果對原圖進行深度優先搜尋,由強連通分量定義已知,任何一個強連通分量是原圖的深度優先搜尋樹的子樹。那麼,只要確定每個強連通分量子樹的根,然後跟據這些根從樹的最低層,一個一個取出強連通分量即可。問題就是如何確定強連通分量的根和如何從最低層開始拿出強連通分量了。
如何確定強連通分量的根,在這裡維護兩個陣列,一個是dfn[maxn],另一個是low[maxn],其中dfn[v]表示頂點v被訪問的時間,low[v]為與頂點v鄰接的未刪除的頂點u的low[u]和low[v]的最小值(low[v]初始化未dfn[v])。這樣,在一次深度優先搜尋的回溯過程中,如果發現low[v]==dfn[v],那麼當前頂點就是一個強連通分量的根。因為如果不是強連通分量的根,那麼一定是屬於另一個強連通分量,而且它的根是當前頂點的祖宗,那麼存在包含當前頂點的到其祖宗的迴路,可知low[v]一定被更改為一個比dfn[v]更小的值。
對於如何取出強連通分量,如果當前節點為一個強連通分量的根,那麼它的強連通分量一定是以該根為根節點的子樹(剩下節點)子樹。在深度優先遍歷中維護一個堆疊,每次訪問一個新節點,就壓入堆疊。由於當前節點是這個強連通分量中最先被壓入堆疊的,那麼在當前節點以後壓入堆疊的並且仍在堆疊中的節點都屬於這個強連通分量。假設一個節點在當前節點壓入堆疊以後壓入並且還存在,同時不屬於該連通分量,那麼一定屬於另一個強連通分量,但當前節點是其根的祖宗,那麼這個強連通分量應該在此之前已經被取出。
時間複雜度分析:時間複雜度為O(n+m)
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1001;
struct edge{
int v,next;
};
edge edges[maxn];
int head[maxn],cnt;
int dfn[maxn],low[maxn],stack[maxn],visit[maxn],tot,index;
void add(int x,int y)
{
edges[cnt].v=y;
edges[cnt].next=head[x];
head[x]=cnt++;
}
void tarjan(int x)
{
dfn[x]=low[x]=++tot;
stack[++index]=x;
visit[x]=1;
for(int i=head[x];~i;i=edges[i].next){
if(!dfn[edges[i].v]){
tarjan(edges[i].v);
low[x]=min(low[x],low[edges[i].v]);
}else if(visit[edges[i].v]){
low[x]=min(low[x],dfn[edges[i].v]);
}
}
if(low[x]==dfn[x]){
do{
printf("%d ",stack[index]);
visit[stack[index]]=0;
index--;
}while(x!=stack[index+1]);
printf("\n");
}
}
int main()
{
memset(head,-1,sizeof(head));
int n,m;
scanf("%d%d",&n,&m);
int u,v;
for(int i=1;i<=m;i++){
scanf("%d%d",&u,&v);
add(u,v);
}
tot=0,index=0;
for(int i=1;i<=n;i++){
if(!dfn[i]){
tarjan(i);
}
}
return 0;
}
相關文章
- 強連通分量(Tarjan演算法)演算法
- 圖論——強連通分量(Tarjan演算法)圖論演算法
- Tarjan求強連通分量
- kosaraju 和 tarjan演算法詳解(強連通分量)演算法
- 【模板】tarjan 強連通分量縮點
- 強聯通分量tarjan
- Tarjan 求有向圖的強連通分量
- 尋找圖的強連通分量:tarjan演算法簡單理解演算法
- 20行程式碼實現,使用Tarjan演算法求解強連通分量行程演算法
- 連通圖與Tarjan演算法演算法
- 強連通分量
- 強連通------tarjan演算法詳解及與縮點聯合運用演算法
- UVA1327 && POJ1904 King's Quest(tarjan+巧妙建圖+強連通分量+縮點)
- 【演算法學習】tarjan 強連通、點雙、邊雙及其縮點 重磅來襲!!!!演算法
- 連通圖演算法詳解之① :Tarjan 和 Kosaraju 演算法演算法
- 強連通分量及縮點 演算法解析及例題演算法
- POJ 1236 Network of Schools 強連通分量
- 無向連通圖點雙連通分量
- 無向連通圖邊雙連通分量
- 有向圖的強連通分量 模版
- UVA-11504 - Dominos(有向圖的強連通分量)
- Day7 割點、割邊和強連通分量
- 邊分治維護強連通分量(CF1989F,P5163)
- Tarjan演算法_縮點演算法
- Day8 雙連通分量
- 抓間諜(強連通)
- tarjan—演算法的神(一)演算法
- 強聯通分量及縮點法
- Tarjan(連通性相關) 筆記筆記
- Tarjan 演算法學習筆記演算法筆記
- tarjan演算法求scc & 縮點演算法
- 有向圖的連通性(判強連通)
- POJ 3694 Network 邊雙連通分量+LCA
- The Bottom of a Graph-POJ2553強連通
- 【Tarjan SCC 加邊使得所有圖聯通 至少選取多少個點能圖聯通 】Network of Schools加強版.md
- 【筆記/模板】無向圖的雙連通分量筆記
- Tarjan
- 一文輕鬆搞定 tarjan 演算法(二)演算法