在上一節我們已經知道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搜尋樹。樹邊 在搜...