建中資訊科校內培訓講義– 圖論
Bebas
11
0
0
Teks penuh
(2) 建中資訊科校內培訓講義 – 圖論 CK6207 楊鈞百. 1-2 名詞與定義 圖論的相關專有名詞十分繁多,在此僅列出部分較重要的名詞與其簡要定義。. A.. 基本定義. 頂點 (Vertex):在圖形中的點。 邊 (Edge):圖形中連接兩個頂點的連線,常常寫成 e(u,v)代表有一條從 u 連到 v 的邊, 而 u 和 v 是其端點。邊是無向的(沒有特定規定的方向),因此 e(u,v) = e(v,u)。 弧 (Arc) :弧可以視為有向的邊,常常寫成 arc(u,v)代表有一條從 u 連到 v 的弧。 由於弧是有向的,因此 arc(u,v)≠arc(v,u)。 相鄰 (Adjacent):無向圖中,兩個點 v 和 u 相鄰當且僅當 v 和 u 之間存在一條邊。 有向圖中,一般若存在一條弧(u,v),則稱 v 和 u 相鄰。 圖 (Graph):一個圖可以用 G = (V,E)來表示,其中 V 是頂點集合,E 是邊集合。. B.. 圖的種類及其他定義. 簡單圖 連通圖 有向圖 無向圖. (Simple graph):沒有環、且沒有多重弧的圖稱作簡單圖。 (Connected graph):對於所有點對之間都至少有一條路徑可以相通。 (Directed graph):若圖中的邊皆為有向邊(弧)則此圖稱作有向圖。 (Undirected graph):若圖中的邊皆為無向邊則此圖稱作有向圖。. 路徑(Path):圖 G 中一個點邊交替出現的序列 p vi0 ei1 vi1 ei2 eik vik ,滿足 vi j V , ei j E ,. ei j (vi j1 , vi j ) 。(亦有人稱之為途徑(walk),而把簡單路徑才稱為路徑) 簡單路徑 (Simple Path):頂點與邊皆不重複的路徑。 分支度 (Degree):一個頂點的度是指與該邊相關聯的邊的條數。 無向圖: deg(v) 2 | E | ;有向圖: deg (v) deg (v) 。(握手定理) vV. vV. vV. 入分支度 (In-degree):在有向圖中,一個頂點 v 的入度是指與該邊相關聯的入邊(即邊的目 標是 v) 條數,記作 deg (v) 。 出分支度 (Out-degree):在有向圖中,一個頂點的出度是指與該邊相關聯的出邊(即邊的起 始端是 v)條數,記作 deg (v) 。 迴路 (或稱圈,Cycle):若有一條路徑可以使一個頂點由自己出發並回到自己,則稱此路徑 為迴路。 子圖 (Sub-graph):G'稱作圖 G 的子圖如果 V (G ') V (G) 以及 E (G ') E (G) 。 生成子圖 (Spanning Sub-graph):即包含 G 的所有頂點的連通子圖,即滿足條件 V (G ') V (G) 的 G 的子圖 G’。 生成樹 (Spanning Tree):設 T 是圖 G 的一個子圖,如果 T 是一棵樹,且 V (T ) V (G) ,則稱 T 是 G 的一個生成樹。即 G 的生成子圖,且子圖為樹。 有向無環圖 DAG (Directed Acyclic Graph):顧名思義,是有向圖且為無環圖。 2| 頁.
(3) 建中資訊科校內培訓講義 – 圖論 CK6207 楊鈞百. Chapter 2 基本知識 2-1 圖的表示法 A.. 鄰接矩陣 (Adjacency Matrix) – Space Complexity: O(V2). 利用一個二維矩陣(陣列)如 adj[u][v] 來記錄頂點 u 與頂點 v 的相鄰狀況,這種表示法 多用於稠密圖(dense graph),優點是可以迅速的修改任意點對的狀態,但有空間複雜度過大 的缺點,在 |V| 過大時恐有記憶體使用量(內存溢出) 上的顧慮。. 對應的鄰接矩陣. B.. 鄰接串列 (Adjacency List) – Space Complexity: O(E). 藉由鏈結串列 (Linked-list)來實作的一種表示法。對於每個節點,用鏈結串列的方式以指 標指向其所鄰接的節點,如果有多個節點鄰接,就以不斷往後串的方式表示之(如下圖)。此 種表示法常用於稀疏圖(Sparse Graph),原因是稀疏圖的邊數相對較少,因此使用鄰接矩陣的 話將會浪費掉大半的記憶體,此時則可以考慮使用鄰接串列。. 對應的鄰接串列. 起點. 終點 指標. 1. 2. 2. 3. 3. NULL. NULL. 2-2 圖的遍歷及走訪 所謂圖的「遍歷」,或者是稱作是「走訪」,意思就是依照著某個順序來一個個訪問圖 中的各個節點,常見的演算法有「深度優先搜尋」及「廣度優先搜尋」,之所以稱作「搜尋」 是因為這些走訪方式亦可以視為是搜索特定節點的方式。然而,雖然演算法的名字是「搜尋」 (Search),但實質上卻是一一走訪各個節點, 因此也有人稱作是「深度 (廣度)優先走訪 (Traversal)」。 3| 頁.
(4) 建中資訊科校內培訓講義 – 圖論 CK6207 楊鈞百. A.. 深度優先搜尋 (Depth-First Search, DFS). I. 基本概念 所謂的深度優先搜尋,顧名思義,我們對於走訪各節點順序採取的是一種「先深」的策 略,意即若考慮一個圖中的點,對於訪問過這個點之後,我們應該首先接著走訪其兒子節點 而非兄弟節點。 II. 特性 DFS 的特性非常顯而易見,由於每次搜尋都是先深入到最底端才「回溯」到上一層找尋 其他可能的路徑,因此不難聯想到堆疊(Stack) 先進後出(FILO) 的特性,因此,對於 DFS 我 們通常使用堆疊實踐,對於層數較少的狀況,亦可以直接寫成遞迴呼叫,利用系統堆疊實踐。 III. DFS 生成樹以及邊的分類 藉由 DFS 遍歷整張圖後,若此圖為連通圖,我們將會得到一棵 DFS-Tree 也就是這張 圖的一棵生成樹,而若非連通圖,則會得到兩棵以上的 DFS-Tree,而若考慮這些 DFS-Tree, 我們可以將 DFS 過程中碰到的邊分作四大類: 1. Tree Edge : 屬於 DFS-Tree 上的邊。 2. Forward Edge: 連向 DFS-Tree 中相對子孫的邊。 3. Back Edge: 連向 DFS-Tree 中相對祖先的邊,加入此邊會造成環。 4. Cross Edge: 非屬以上三種的邊即為 Cross Edge。 IV. 虛擬碼 Function DFS ( bool[ ] Visited, int Start, stack Stack ) 1 Set Visited[ ] all False. 3 push Start into Stack.. //將起點放入堆疊. 4 5 6 7. //若堆疊頂端的點尚未遍歷. 8 9 10 11 12. While Stack is not empty Do Curr←top element of Stack. Pop the top element of Stack. If Visited[Curr]=False Then Visited[Curr] ← True. For Next, all vertices adjacent to Curr Do Push Next into Stack. End If. End While.. 使用的資料結構為鄰接矩陣的話,可以以 O(V2) 的時間遍歷整張圖;使用鄰接串列的話, 則可以用 O(V+E) 的時間遍歷整張圖。 4| 頁.
(5) 建中資訊科校內培訓講義 – 圖論 CK6207 楊鈞百. B.. 廣度優先搜尋 (Breadth-First Search, BFS). I. 基本概念 相對於深度優先搜尋,如其名,走訪順序相對於 DFS 的深度優先,BFS 改採廣度優先 的策略,意思是對於圖中的某一節點,拜訪過後是先接著拜訪「同一層」的兄弟節點,之後 才拜訪子孫節點。(所謂的「層數」是指在 BFS Tree 中和起始點的距離) II. 特性 BFS 最重要的特性其實也十分顯著,由於其「先廣」的策略,簡單來說就是一種自原點 「擴散」的概念。觀察一下就會發現,由於對於每一個節點都是先拜訪同層節點之後再拜訪 下一層的節點,因此,我們將可以保證,每個節點被拜訪到後在 BFS-Tree 中的位置其與起始 點(即 BFS-Tree 中的根結點, Root) 的距離必定為最短。 由於 BFS 永遠是先拜 訪同層的點,換句話說,對於每個點接下來下一層將被考慮的點 一定是比較晚被拜訪的,這讓我們聯想到佇列(Queue)先進先出(FIFO) 的特性,因此,我們 可以以維護一個佇列來實作 BFS。 III. 虛擬碼 Function BFS ( bool[ ] Visited, int Start, queue Queue ) 1 Set Visited[ ] all False. 2 Visited[Start] ← True. \ 3 push Start into Queue. 4 5 6 7. While Queue is not empty Do Curr←front element of Queue. pop the Queue. For Next, all vertices adjacent to Curr. 8 9 10. If Visited[Next]=False Then Visited[Next]←True. push Next into Queue.. 11. End if.. 12. //將起點放入佇列. //找出相鄰且尚未遍歷的點. //將他們放入佇列. End While.. 虛擬碼整體而言跟 DFS 大同小異,唯獨將 Stack 換成 Queue。 使用的資料結構為鄰接矩陣的話,可以以 O(V2) 的時間遍歷整張圖;使用鄰接串列的話, 則可以用 O(V+E) 的時間遍歷整張圖。 ~ Note ~. 5| 頁.
(6) 建中資訊科校內培訓講義 – 圖論 CK6207 楊鈞百. C.. 拓樸排序 (Topological Sort). I. 基本概念 拓樸排序的名字中雖有「排序」二字,但他與我們所熟知的一些序列排序演算法如 QuickSort、Merge Sort 等不同,拓樸排序所「排序」的對象是圖,對於一張有向圖,我們可以藉 由拓樸排序來得到一個拜訪順序使得當一個節點被拜訪時,其入分支的所有來源節點都已經 被拜訪,可以參考下面的附圖。 此外,拓樸排序顯然不一定都只有唯一解。 II. 條件限制 知道了拓樸排序的用意後,我們不難發現到,對於一個有 Cycle 的圖,我們是無法利用 拓樸排序對其得到一個符合條件的拜訪順序的,理由是因為形成 Cycle 的那些節點彼此是彼 此的前序節點,意思就是 Cycle 中沒有一個節點可以符合拜訪條件。因此,我們只能對一張 有向無環圖 (DAG) 作拓樸排序的作業。 III. 時間戳記 (Time Stamp) 現在,我們要引進一種叫做「時間戳記」的標號(Label) 概念,所謂的一個節點的時間戳 記,意思就是在走訪這張圖時進出該節點的時間點,時間戳記的概念可以幫助我們解決一些 問題。 IV. 演算法 對於拓樸排序這個問題,我們便可以利用剛剛所提到的時間戳記的概念解決。首先,以 DFS 遍歷一次整張圖,並在過程中記錄下各個節點訪問結束的時間點,而最後我們可以很容 易的得到拓樸排序的結果,只要將時間戳記的標號順序反過來就可以了 V. 實際應用 拓樸排序有很多的應用,可以參考相關書籍,其中一個很直覺的用途就是可以拿來排定 事務處理的順序等等有「先決條件」(意即在做某些事前須先完成某些事) 的事情。 6| 頁.
(7) 建中資訊科校內培訓講義 – 圖論 CK6207 楊鈞百. VI. 虛擬碼 Function Topological_Sort ( bool[ ] Visited, stack Stack, int[ ] Stamp ) 1 2 3. Time←0. Set Visited[ ] all False. For All the vertex V in the DAG. 4 5 6 7 8 9 10 11 12. Do If Visited[V]=False Then Visited[V] ← True. push V into Stack. While Stack is not empty Do Curr←top element of Stack pop the Stack. Time←Time+1 Stamp[Time]←Curr. For Next, all vertices adjacent to Curr. 13 14 15 16 17 18. //初始化時間為 0. //對 DAG 作一遍 DFS. //時間戳記, //記錄該時間被拜訪的節點. If Visited[Next]=False Then Visited[Next]←True. push Next into Stack. End if. End While. End if.. 使用的資料結構為鄰接矩陣的話,可以以 O(V2) 的時間對頂點進行拓樸排序;使用鄰接 串列的話,則可以用 O(V+E) 的時間對頂點進行拓樸排序。. 想一想? ※請比較遍歷圖的 D/BFS 與狀態搜索的 D/BFS 之異同。 ※為什麼 BFS 有各節點在 BFS-Tree 中層數必為可能的最小值但 DFS 卻沒有此特性? ※為何將 DFS 時所記錄的時間戳記順序顛倒過來就必定是一種合法的拓樸排序順序呢?. Do Exercise !. 2-2. UVa : 336, 10305, 10926, 10959 TIOJ : 1092 7| 頁.
(8) 建中資訊科校內培訓講義 – 圖論 CK6207 楊鈞百. 2-3 圖的連通性與元件 我們如果要檢驗一個圖的連通性,可以使用前面提到的深度優先走訪(DFS),但在 DFS 的過程中,我們除了可以查詢此圖的連通塊以外,其實只要加一些記錄,就可以得到很多有 用的相關訊息。 因此,這節我們將從基本的 DFS 延伸下去,說明這些能夠利用 DFS 得到的資訊。. A.. 無向圖的「關鍵點」 (或稱 割頂 , Articulation Point). I. 基本概念 無向圖的關鍵點的集合是該無向圖頂點集合中的一個特殊子集合,一個頂點被我們稱為 關鍵點若且為若該無向圖只要拔掉該頂點則該無向圖不連通,而這個性質使得關鍵點有它的 重要性存在。 II. 性質 1. 考慮 DFS-Tree 中的根節點 (Root): 如果有兩個節點 A、B 在 DFS-Tree 中皆為根節點(Root) 的兒子,則 A 必無法經由 其他的邊與 B 相連,因此,此時根節點(Root) 顯然為一關鍵點。 2. 考慮 DFS-Tree 中的非根節點 v: 設 v 的某個兒子節點為 u,則可以發現,如果 u 與 u 的子孫節點都不存在指向 v 的 Back Edge,則刪除 v 之後,u 必然無法跟 v 的祖先或是兄弟節點連通,因此,此時 v 即 為一關鍵點。 III. 演算法 我們可以對於每個節點,多維護兩個值,一個是該節點在 DFS-Tree 中的深度,我們先稱 之為該節點的 dep 值;另一個則是該節點在 DFS-Tree 中的所有 Back Edge 之中,最小可以連 接到深度多小的節點,我們先稱之為該節點的 low 值。 有了 dep 值和 low 值之後,我們就可以很容易的得到一個求無向圖中關鍵點的演算法: 對於根節點,只要在 DFS-Tree 中的兒子節點超過兩個,則根節點為關鍵點;對於其他節點 v, 只要兒子節點 u 的 low 值大於等於該節點 v 的 dep 值,則節點 v 為關鍵點。. 8| 頁.
(9) 建中資訊科校內培訓講義 – 圖論 CK6207 楊鈞百. VI. 虛擬碼 Function Find_AP ( bool[ ] Visited, int Start, int[ ] Dep, int[ ] Low, List AP ) 1 2 3 4. Set Visited[ ] all False. Visited[Start] ← True. Clear List AP. DFS( Visited, Start, NIL, 0, Dep, Low, AP ).. Function DFS ( bool[ ] Visited, int Curr, int Prev, int Depth, int[ ] Dep, int[ ] Low, List AP ) 1 Visited[Curr] ← True. 2 Dep[Curr] ← Depth. 3 Count ← 0. //計算當前節點 Curr 的兒子數 4 5 6 7 8 9 10 11 12 13 14 15. For Next, all vertices adjacent to Curr If Visited[Next]=True And Next is not Prev Then Low[Curr] ← Min{ Low[Curr], Dep[Next] }. End if. If Visited[Next]=False Then DFS( Visited, Next, Curr, Depth+1, Dep, Low, AP ). Count ← Count+1. If (Depth=0 And Count>1) Or (Depth>0 And Low[Next]≧Dep[Curr]) Then If Curr is not in the List AP, Add Curr to The List AP. End if. End if. End For.. 由於僅僅是在 DFS 上做額外的標記動作,故時間複雜度與普通的 DFS 相同。 使用的資料結構為鄰接矩陣的話,可以以 O(V2) 的時間求出圖的所有關鍵點;使用鄰接 串列的話,則可以用 O(V+E) 的時間求出圖的所有關鍵點。. More Extend Ext. 無向圖的「橋」 (Bridge) 無向圖的橋的集合是該無向圖邊集合中的一個特殊子集合,一條邊被我們之稱為橋若 且為若該無向圖只要拔掉該條邊則該無向圖不連通。 不覺得「橋」的概念和剛剛提到的關鍵點(Articulation Point) 很像嗎?只是一個是頂點 一個是邊,其實,求出無向圖中的橋的方法與求關鍵點的大小是大同小異的,你能夠自己 想出如何求出那些邊是橋嗎?. 9| 頁.
(10) 建中資訊科校內培訓講義 – 圖論 CK6207 楊鈞百. 所謂的「連通元件」(Connected Component) 是一個有向圖或無向圖的子圖,且該子圖滿 足任兩個節點皆互相連通,而且無法在維持該性質下加入任何其他的頂點或邊──換句話說, 就是一個極大的連通子圖 (Maximal Connected Subgraph)。. B.. 有向圖的「強連通元件」 (Strongly-Connected Component, SCC). I. 基本概念 如果一個有向圖中的每一個頂點對於其他的每個節點都存在著一條路徑(Path) 能夠到達, 則我們稱該有向圖「強連通」(Strongly Connected)。 因此,一個有向圖的「強連通元件」即為該有向圖的一個極大強連通子圖。 II. 性質 有向圖的強連通元件有一個很重要的性質。當我們求出一個有向圖的強連通元件之後, 我們可以把整個強連通元件視作一個點,該點對於不在所處強連通元件的節點的邊即為該強 連通元件中所有點對外的邊,這個動作我們稱之為「縮點」。而在縮完一個有向圖中所有的 強連通元件之後,該有向圖便會成為一個有向無環圖 (DAG)。 這個縮點的概念與技巧很重要,不僅僅在 SCC 的部分會用到相關概念,之後在其他地方 也有可以能會用到。 III. 演算法 求 SCC 有許多經典的演算法,在此我們介紹其中一種稱為「Kosaraju’s Algorithm」的 演算法。 首先,先對原本的有向圖 G0 作一次 DFS 走訪,而在遍歷節點的過程使用之前曾經使用 過的時間戳記(Time Stamp),對每個節點結束遍歷的時間建立時間戳記。在第一次 DFS 走訪 之後,我們會得到一座森林(Forest) F0,之後對於 F0 中的每一棵樹 Ti,Ti 中的節點與連結那些 節點的邊形成一個圖 Gi,對於這些 Gi,我們將其中的邊全部反向,得到一個新的圖 GiT,之 後再按照剛剛做的時間戳記由大到小的順序對 GiT 進行 DFS 走訪,然後又會得到一座新的森 林 Fi,而對於 Fi 中的每一棵樹,樹中的節點連接那些節點的邊(不一定在樹中)即成一個強連 通元件(SCC)。. 10 | 頁.
(11) 建中資訊科校內培訓講義 – 圖論 CK6207 楊鈞百. VI. 虛擬碼 Function Kosaraju’s_Algorithm ( Graph G, bool[ ] Visited, int[ ] Stamp, List SCC ) 1 2 3 4 5 6 7 8 9 10 11. Clear List SCC. Set Visited[ ] all False. For v, all vertices in G If Visited[v]=False Then start DFS G from v and make Time Stamp. End If. Let GT be G with reversed arcs. Set Visited[ ] all False. For u, with the reverse order of Time Stamp If Visited[u]=False Then Clear Current SCC.. 12. start DFS GT from u and add the vertices into Current SCC which were visited during the DFS.. 13 14. add Current SCC to List SCC. End If.. More Extend Ext. 無向圖的「雙連通元件」 (Bi-Connected Component, BCC) 對於一個無向圖,若在該無向圖中的每個點皆不為關鍵點(Articulation Point),則我們 稱該無向圖「雙連通」(Bi-Connected)。 因此,一個無向圖中的雙連通元件即為該無向圖中的一個「極大雙連通子圖」。 雙連通元件也具有一些獨特的性質,對於一個雙連通元件中的兩個任意頂點,都至少 有兩條相異的路徑連接它們。此外,如果我們將一個無向圖的所有 BCC 全部收縮成點, 我們可以得到一棵樹,而這棵樹的邊就是橋! 想一想,要如何求出一個無向圖的 BCC?這些性質又該怎麼應用呢?. 想一想? ※為什麼求 SCC 的 Kosaraju’s Algorithm 會是對的? ※試著分析看看 Kosaraju’s Algorithm 的時間複雜度。 ※為什麼將一個有向圖中的所有 SCC 縮成單一個點之後該圖就會成為一個 DAG?. Do Exercise !. 2-3. UVa : 10199 TIOJ : 1137. 11 | 頁.
(12)
Dokumen terkait
◎請閱讀下列敘述後,回答72~73題: 太陽能是一種再生能源,其中一種太陽能發電方式是使用如下圖一所示的拋物面碟式收集 器來收集太陽能。圖中的反射器可使太陽光會聚於接收器,加熱流經接收器內部的物質,進 而達到發電的目的。 下圖二為接收器內部構造的示意圖,其內部為一個不鏽鋼管,外罩一個玻璃外殼,玻
【志願選填操作說明】以下學校排序無具代表任何意義 操作方法一:使用[滑鼠游標 ]將「可選學校」區塊之[學校名稱]方塊拖曳到「志願序」區塊中,進 行排序如圖一。 若「志願順序」需要調整序,可直接使用拖曳方式進行。如圖二 操作方法二:使用[選取方塊]將需要排序或需移除的學校進行勾選,再點選 或