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演算法)圖論演算法
- Tarjan演算法求強連通分量總結演算法
- 強連通分量-tarjan演算法模板詳解演算法
- kosaraju 和 tarjan演算法詳解(強連通分量)演算法
- Tarjan演算法三大應用之強連通分量演算法
- 強連通分量及縮點tarjan演算法解析演算法
- 【模板】tarjan 強連通分量縮點
- Tarjan 求有向圖的強連通分量
- 尋找圖的強連通分量:tarjan演算法簡單理解演算法
- POJ 2186 Popular Cows(強連通分量縮點,Tarjan演算法)演算法
- 20行程式碼實現,使用Tarjan演算法求解強連通分量行程演算法
- 圖論複習之強連通分量以及縮點—Tarjan演算法圖論演算法
- 強連通演算法--Tarjan個人理解+詳解演算法
- 強連通分量與縮點(Tarjan演算法)(洛谷P3387)演算法
- 連通圖與Tarjan演算法演算法
- 強連通分量
- HDU 2767 Proving Equivalences Tarjan 強連通縮點UI
- 強連通------tarjan演算法詳解及與縮點聯合運用演算法
- 演算法學習之路|強連通分量+縮點演算法
- 【筆記】tarjian演算法 求強連通分量筆記演算法
- 【演算法學習】tarjan 強連通、點雙、邊雙及其縮點 重磅來襲!!!!演算法
- 連通圖演算法詳解之① :Tarjan 和 Kosaraju 演算法演算法
- 強連通分量及縮點 演算法解析及例題演算法
- 強連通圖的演算法演算法
- Trajan演算法(強連通+縮點)演算法
- HDU2767Proving Equivalences[強連通分量 縮點]UI
- 求有向圖的強連通分量(c語言版)C語言
- Tarjan演算法_縮點演算法
- 抓間諜(強連通)
- 邊分治維護強連通分量(CF1989F,P5163)
- tarjan—演算法的神(一)演算法
- Tarjan(連通性相關) 筆記筆記
- 有向圖的連通性(判強連通)
- tarjan演算法求scc & 縮點演算法
- Tarjan 演算法學習筆記演算法筆記
- 【Tarjan SCC 加邊使得所有圖聯通 至少選取多少個點能圖聯通 】Network of Schools加強版.md