tarjan演算法求割點割邊

2021-09-03 02:50:48 字數 3244 閱讀 2509

在上一節我們已經知道tarjan演算法可以求聯通圖,在這裡我們也運用tarjan的思想求割點與割邊,首先我們先來說說割點,那麼什麼事割點呢,先來看一張圖(a),來自網路

在(a)圖中,我們將a點以及與a點相連的邊全部去除,會發現這個聯通圖被分成了倆個聯通圖,乙個是節點f,另外乙個是餘下的所有的節點組成的圖,因此我們將a點稱為割點,同理我們發現b點也是割點,因此我們可以這樣定義割點,在乙個無向聯通圖中,如果刪除某個節點後,圖不再連通(即任意倆點之間不能相互到達),我們稱這樣的頂點為割點(定義來自啊哈演算法),那麼問題來了,如何求割點呢???

很容易的乙個想法就是我們每次刪除乙個節點後用bfs或者dfs來遍歷圖是否依然聯通,如果不聯通則該點是割點,這種方法的複雜度是o(n(n + m)),太暴力了,我們來想想其他的方法

再介紹其他方法前,我們再來了解幾個定義(定義**於網路)

通過觀察圖(2),我們發現有倆類節點可能成為割點

對根節點u,若其有兩棵或兩棵以上的子樹,則該根結點u為割點;(說明刪除該節點會產生至少倆棵不聯通的子樹)

對非葉子節點u(非根節點),若其子樹的節點均沒有指向u的祖先節點的回邊,說明刪除u之後,根結點與u的子樹的節點不再連通;則節點u為割點。(在這裡可以簡單畫個圖理解一下)

對於這倆類節點,前者我們很容易判斷,我們就不做過多的說明了,具體的判斷會在**裡面講解,我們來說說後者的判斷

我們用dfn[u]記錄節點u在dfs過程中被遍歷到的次序號,low[u]記錄節點u或u的子樹通過非父子邊追溯到最早的祖先節點(即dfs次序號最小),那麼low[u]的計算過程如下:

low[u]=,((u,v)為樹邊)

low【u】 = min    (u,v)為回邊且v不為u的父親節點

至於為什麼不為u的父親節點我暫時還沒有想明白......

那麼對於第二類節點,當(u,v)為樹邊且low[v] >= dfn[u]時,節點u才為割點。該式子的含義:表示v節點不能繞過u節點從而返回到更早的祖先,因此u節點為割點

下面來看**實現,在**裡面會做詳細的解說

#include#includeusing namespace std;

int n, m, root, a, b, total;

int e[101][101], dfn[101], low[101], flag[101], head[101];

struct nodeedge[10010];

int cnt = 1;

//前向星建圖

void add(int u, int v)

void tarjan(int u, int father) else if (u != root && low[v] >= dfn[u])

//如果頂點被訪問過並且不是該節點的父親,說明此時的v為u的祖先,因此需要更新最早頂點的時間戳

} else if (v != father)

}}int main()

root = 1; //假設1為根節點

//從1號頂點開始進行深度優先搜尋(tarjan)

tarjan(1, root);

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

}return 0;

}

給一組資料拿來測試一下該**

6 7(6個頂點,7條無向邊)

1 41 3

4 23 2

2 52 6

5 6輸出為 2

如果有多**,那麼我們使用另外的一組**,見下

#includeusing namespace std;

const int maxn = 20010;

const int maxv = 200010;

int cnt = 1, n, m, total, a, b;

int head[maxn], flag[maxn], dfn[maxn], low[maxn], sum;

struct nodeedge[maxv];

void add(int u, int v)

void tarjan(int u, int father)

if (u == father) child++;

}low[u] = min(low[u], dfn[v]);

}if (child >= 2 && u == father)

}int main ()

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

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

cout << sum << endl;

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

}return 0;

}

了解完割點後我們再來了解什麼是割邊,其實很簡單,即在乙個無向聯通圖中,如果刪除某條邊後,圖不在聯通,那麼該條邊稱為割邊,**和上面的**基本上一模一樣,只要改乙個小地方,就是將low【v】 >= dfn[u] 改為 low【v】> dfs

[u]即可,前者便是還可以回到父親,後者表示連父親都回不到了,倘若頂點v不能回到祖先,也沒有另外一條路可以回到父親,那麼u-v這條邊就是割邊,其實仔細想想模擬個圖就明白了,**實現如下

#include#includeusing namespace std;

int n, m, root, a, b, total;

int e[101][101], dfn[101], low[101], flag[101], head[101];

struct nodeedge[10010];

int cnt = 1;

void add(int u, int v)

void tarjan(int u, int father)

} else if (v != father)

}}int main()

root = 1;

tarjan(1, root);

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

}return 0;

}

如果輸入上面的那組資料那麼不會有輸出,因為沒有割邊,再給出一組資料

6 61 4

1 34 2

3 22 5

5 6輸出5->6

2->5

割點和割邊就解釋到這裡了,完畢

tarjan求割邊割點

內容及 來自 割邊 在連通圖中,刪除了連通圖的某條邊後,圖不再連通。這樣的邊被稱為割邊,也叫做橋。割點 在連通圖中,刪除了連通圖的某個點以及與這個點相連的邊後,圖不再連通。這樣的點被稱為割點。dfs搜尋樹 用dfs對圖進行遍歷時,按照遍歷次序的不同,我們可以得到一棵dfs搜尋樹。樹邊 在搜尋樹中的藍...

tarjan求割點和割邊

概念 割點 在乙個無向圖中,如果刪除某個頂點,這個圖就不再連通 任意兩點之間無法相互到達 那麼這個頂點就是這個圖的割點。割邊 橋 在乙個無向圖中刪除某條邊後,圖不再連通,那麼這條邊就是這個圖的割邊 也叫作橋 求法 x 為樹根,且 x 有多於乙個子樹。x 不為樹根,且滿足 x 為 to 在搜尋樹中的父...

割點 割邊 tarjan

洛谷割點模板題 傳送門 割邊 在連通圖中,刪除了連通圖的某條邊後,圖不再連通。這樣的邊被稱為割邊,也叫做橋。割點 在連通圖中,刪除了連通圖的某個點以及與這個點相連的邊後,圖不再連通。這樣的點被稱為割點。dfs搜尋樹 用dfs對圖進行遍歷時,按照遍歷次序的不同,我們可以得到一棵dfs搜尋樹。樹邊 在搜...