Tarjan演算法介紹

2022-03-30 07:42:50 字數 2349 閱讀 5321

一種由robert tarjan提出的求解有向圖強連通分量的線性時間的演算法。

給定無向圖\(g=(v,e)\)

如果割掉點x,圖中的連通塊數量增加,則稱x為g的割點

如果割掉邊e,圖中的連通塊數量增加,則稱e為g的割邊

在圖的深度優先搜尋中,按照每個節點的訪問順序所給每個點編的號,該編號叫做「時間戳」,記為dfn[x]

在無向連通圖中任選乙個節點出發進行深度優先搜尋,每個點只訪問一次。所有遞迴的邊構成的一棵樹稱為搜尋樹,所有形成環的邊稱為返祖邊

追溯值low[x]表示在x為根的子樹內,所有邊中能夠到達的點的最小的dfn(不包括父親節點)。

如果一條邊(x,y)是一條返祖邊,\(low[x]=min(low[x],dfn[x]);\)

如果一條邊(x,y)是搜尋樹上的邊,\(low[x]=min(low[x],low[y]);\)

如果一條無向邊(x,y)是一條橋,一定滿足$$dfn[x]\(low[y]>dfn[x]\),所以在y節點的子樹內一定沒有一條邊可以到達x或比dfn[x]還要小的點。

如果乙個點x是割點,一定滿足$$dfn[x]\leq low[y]$$

證明:因為\(dfn[x]\leq low[y]\),所以在以y點為根的子樹內一定沒有一條邊可以跳到x以上,所以當x割掉,子樹將獨立

若一張無向聯通圖不存在割點,則稱它為點雙連通圖,若一張無向聯通圖不存在橋,則稱它為邊雙連通圖

無向圖中極大的點雙連通子圖叫點雙連通分量,極大的邊雙連通子圖叫邊雙連通分量,統稱為雙連通分量

邊雙連通分量(e-dcc)的求法

把無向圖中的所有橋都刪去,得到的就是若干個邊雙。

邊雙縮點

在某些時候,我們需要把邊雙縮成乙個點使得原本的連通圖變成乙個我們可以容易做的樹,這種操作就是把乙個大的邊雙連通分量用乙個點代替。

首先我們找到\(low[x]=dfn[x]\)的點,這必定是乙個邊雙的根。

證明:對於乙個邊雙,我們知道在這個邊雙內沒有一條橋。既然滿足\(low[x]=dfn[x]\),則在x的子樹內沒有乙個點有連邊到該點的上面,所以仍在棧中的點一定是以x為根的邊雙。

我們可以用乙個棧來儲存我們經過的點,一旦這個點成為了雙連通分量中的點,就可以將其彈棧。

code:

void tarjan(int x,int fa)

}

人工棧
void tarjan(int x)

int i=cur[x];

if(i)

} if(low[x]==dfn[x])--stack[0];

} --index;low[f[index]]=min(low[f[index]],low[f[index+1]]);

}}

點雙連通分量(v-dcc)的求法

對於點雙連通分量,需要在tarjan裡面維護乙個棧,每次將當前搜尋到的點加入棧中,當你發現x點滿足割點條件的時候,那麼仍在棧裡的點就是乙個以x為根的點雙,把他們全部彈掉(注意:割點不要彈掉,因為乙個割點有可能存在於在多個點雙中)

點雙的縮點

由於乙個割點有可能存在於多個點雙之中,所有點雙的縮點不能像邊雙一樣直接用橋邊相連,我們需要新建節點來代表某個割點,用它把所有這個割點所在的點雙連線起來。

對於一幅圖

它擁有的點雙就有

那麼縮完點就是

code:

void tarjan(int x,int fa)

}else low[x]=min(low[x],dfn[tov[i]]);

}cnt=tot;

for (i=1;i<=n;++i) if(cut[i]) new_id[i]=++tot;

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

for (j=0;j<=dcc[i][0];++j)

else c[x]=i;//除割點外,其他點僅屬於1個v_dcc

}

Tarjan演算法介紹

tarjan演算法是圖論中的一種演算法,用作於圖的聯通性 如果沒學過這樣東西的人可以先收藏一下,等學過了在看 targan演算法的流程 利用dfs來遍歷圖來構建一種數型的結構 tarjan演算法的兩個核心陣列 dfn 我們用dfn陣列記錄 low 我們用low i 表示乙個節點的子樹中可以到達最小的...

tarjan演算法原理介紹

證明比較繁瑣,仔細檢查了應該沒有大錯,記錄一下證明過程。在有向圖中,強連通分量的定義是 有向圖的某個子圖,其中任意兩個點之間可以互達。定理1 乙個完整的強連通分量一定包含在一棵深度優先搜尋樹中。定理2 子圖是強連通分量 子圖中的每一條路徑都歸屬於乙個環狀 除非只有乙個點 證明 根據強連通分量的定義,...

tarjan演算法詳解

參考 tarjan演算法在強連通分量分離中運用很廣,書寫簡單,並且可以拓展到圖的割點,割邊上,十分強大 具體思路 令dfn u 表示當前點的時間戳 low u 表示當前點所能到達的點的時間戳中最小的乙個 到達點u時,將其入棧 拓展點u後代 當且僅當dfn u low u 時,棧頂元素全部出棧,此時出...