Preface:
考慮有下面網路拓譜圖, 當你是一個網管, 可能會希望找出當那些點 break 後則可能會造成部分的子網路無法連線而加以改善: (下面例子即是實驗室與 215 機房 的 switch)
而你可以把網路拓譜圖視為一個 Connected graph, 而我們的目標便是找出 Argiculation point:
以下面左邊的圖形為範例, Vertex 1, 3, 5 與 7 即為 Argiculation point:
Use DFS to find Articulation point:
底下說明使用 DFS (Deep First Search) 來找出 Articulation point. 首先第一步便是決定 Graph 的某一點開始跑 DFS 並標示出每點的 discover time. 假設我們取 Vertex 3 為 root 跑 DFS, 則一種可能的走法如下: (3-4-2-1-0-5-6-7-9-8)
接著我們將 Vertex 3 視為 root 並調整長相如下 (虛線為 back edge):
然後我們使用下面公式計算每一點的 low 值:
計算結果如下:
接著只要滿足下面任一個條件即為 Articulation point:
以上面的例子來說, 因為 Root vertex 3 有兩個 child (Vertex 4,5), 故 Vertex 3 為 Articulation point; Vertex 1 的 d=3, 而其 child Vertex 0 的 low 值為 4, 故 Vertex 1 為 Articulation point... 眼尖的你應該可以發現只要 Vertex u 的 child(s) 都有 back edge 回到 Vertex u 的祖先, 則 Vertex u 就不會是 Articulation point!
Implementation:
底下類別實作了上面利用 DFS 找 Articulation point 的過程: (完整代碼)
Example:
底下為該類別使用的一個範例:
執行結果:
Supplement:
* [CSIE 1212] Data Structure and Algorithm - 4/9 Graph2
* Articulation Vertex / Bridge
* [ Intro Alg ] Elementary Graph Algorithms - Depth-first search
考慮有下面網路拓譜圖, 當你是一個網管, 可能會希望找出當那些點 break 後則可能會造成部分的子網路無法連線而加以改善: (下面例子即是實驗室與 215 機房 的 switch)
而你可以把網路拓譜圖視為一個 Connected graph, 而我們的目標便是找出 Argiculation point:
以下面左邊的圖形為範例, Vertex 1, 3, 5 與 7 即為 Argiculation point:
Use DFS to find Articulation point:
底下說明使用 DFS (Deep First Search) 來找出 Articulation point. 首先第一步便是決定 Graph 的某一點開始跑 DFS 並標示出每點的 discover time. 假設我們取 Vertex 3 為 root 跑 DFS, 則一種可能的走法如下: (3-4-2-1-0-5-6-7-9-8)
接著我們將 Vertex 3 視為 root 並調整長相如下 (虛線為 back edge):
然後我們使用下面公式計算每一點的 low 值:
計算結果如下:
接著只要滿足下面任一個條件即為 Articulation point:
以上面的例子來說, 因為 Root vertex 3 有兩個 child (Vertex 4,5), 故 Vertex 3 為 Articulation point; Vertex 1 的 d=3, 而其 child Vertex 0 的 low 值為 4, 故 Vertex 1 為 Articulation point... 眼尖的你應該可以發現只要 Vertex u 的 child(s) 都有 back edge 回到 Vertex u 的祖先, 則 Vertex u 就不會是 Articulation point!
Implementation:
底下類別實作了上面利用 DFS 找 Articulation point 的過程: (完整代碼)
- package map.alg;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Set;
- import java.util.TreeSet;
- import map.Edge;
- import map.Graph;
- import map.Vertex;
- import map.enums.EEdgeType;
- public class FindArtiCulationPt {
- /**
- * BD: low(v)=min{v.d, min{low(w)|w is a child of v}, min{w.d| (v,w) is a back edge}}
- * @param v
- */
- protected static void _CalcLow(Vertex v)
- {
- int low = Integer.MAX_VALUE;
- for(Edge e:v.edgeSet)
- {
- if(e.to.d > v.d) // children
- {
- _CalcLow(e.to);
- low = Math.min(low, e.to.low);
- }
- else if(e.type.equals(EEdgeType.Back)) low = Math.min(low, e.to.d); // back edge
- }
- v.low = Math.min(low, v.d);
- }
- public static Set
Go(Graph g, Vertex s) - {
- Set
vset = new TreeSet (); - // 1) Run DFS
- DFS.Run(g, s);
- // 2.1) 如果是root的話(開始做dfs的地方), 且有超過一個的 children 是articulation point
- s.low = 1;
- List
childList = new ArrayList (); - for(Edge e:s.edgeSet)
- {
- if(e.type.equals(EEdgeType.Tree)) {
- System.out.printf("\t[Test] Child=%s\n", e.to);
- childList.add(e.to);
- }
- }
- if(childList.size()>1) vset.add(s);
- // 2.2) 當有一個以上的小孩,
- // 無法沿著它自己的後代及一條nontree edge (back edge)到達它的祖先的時候, 則為articulation point
- for(Vertex v:childList) _CalcLow(v);
- for(Vertex v:g.vtxMap.values())
- {
- for(Edge e:v.edgeSet)
- {
- if(e.to.d>v.d && e.to.low>=v.d)
- {
- vset.add(v);
- break;
- }
- }
- }
- return vset;
- }
- }
底下為該類別使用的一個範例:
- public static void main(String[] args) {
- Graph g = new Graph(false);
- g.addVertice(0, 9);
- g.addEdge(0, 1);
- g.addEdge(1, 2); g.addEdge(1, 3);
- g.addEdge(2, 4);
- g.addEdge(4, 3);
- g.addEdge(3, 5);
- g.addEdge(5, 6); g.addEdge(5, 7);
- g.addEdge(6, 7);
- g.addEdge(7, 8); g.addEdge(7, 9);
- Set
vset = FindArtiCulationPt.Go(g, g.getVertex(3)); - System.out.printf("\t[Info] Articulation Point:\n");
- for(Vertex v:vset) System.out.printf("\t\t%s\n", v);
- }
Supplement:
* [CSIE 1212] Data Structure and Algorithm - 4/9 Graph2
* Articulation Vertex / Bridge
* [ Intro Alg ] Elementary Graph Algorithms - Depth-first search
沒有留言:
張貼留言