求一個無向連通圖的割點。
割點的定義:
若除去此結點和與其相關的邊,無向連通圖不再連通。
最簡單直接的辦法:
利用BFS或DFS可以用來判斷圖連通性的性質(即根據一次深搜或廣搜能否遍歷圖所有的頂點來判斷圖的連通性)。
判斷一個點是不是割點,先把這個點和相關的邊從圖中去掉, 然後用BFS或者DFS來判斷剩下圖的連通性。
這種算法適合判斷一個點是否爲割點,但是如果要去求所有的割點,算法的時間複雜度:O(V*(V+E))。
要思考一個適合去找圖的割點集的算法。
算法思路:
對於一棵 DFS 搜索樹:
1)根結點:當且僅當根節點至少有兩個兒子時,其是割點
2)其他點:對於其他點 v,當僅有一個兒子 u 時,從 u 或 u 的後代出發,沒有指向 v 祖先(不含 v)的邊,則刪除 v後,u 和 v 的父親不連通時,v 是割點
算法過程:(基於 tarjan算法)
1)對圖進行 Tarjan 算法,得到 dfn 和 low 兩個數組;dfn來表示訪問的時間(次序) low[a]來表示 a能夠追溯到的祖先節點
2)每遍歷一個新的 u 的兒子 v 都記錄個數
3)low[u] 值更新後進行以下判斷(前提:v 未被遍歷):
① u 爲樹根,且兒子個數大於 1
② u 不爲樹根,但 low[v]>=dfn[u]
滿足以上任意條件 u 便爲割點,記錄在一數組裏,Tarjan 完成後再輸出即可(中途輸出會重複)
證明過程:
(1) 當a節點是dfs樹中的根節點時 如果a有兩個或者兩個以上的子樹則說明a是割點
(2)b節點在dfs樹中是a的子樹中的節點 low[b]>=dfn[a] 則說明a是割點
證明(1)
a爲根節點 則low[a]=dfn[a]=1 假設b是其子樹中的節點 則必有low[b]>=dfn[a] 則條件2必成立 則說明當a點爲dfs樹中的根節點時,條件2失去了其判斷作用 當要判斷的點爲dfs樹的根節點時 條件2無法判斷
根節點是否是割點 所以應特殊情況特殊分析
a是dfs樹中的根節點 b和c分別是a的子樹 則如果當通過a對b進行dfs後
沒有訪問到c則說明b和c之間沒有任何直接連通的路徑 則a爲割點
也就是說當在dfs樹中a的子樹超過1則說明a爲割點
證明(2)
a爲非葉節點非根節點時 當b爲a中的子樹中的節點時 如果a是割點則說明 b必須通過a纔可以和a的父節點 或者a的兄弟節點連通 則b能夠追溯到則最早的節點即low[b]>=dfn[a]
原文鏈接:https://blog.csdn.net/HE19930303/article/details/47069989