270 likes | 398 Views
7.5 擴張樹 (Spanning Tree). 一個無向相連圖 G 的子圖 G’ 如果可用最少的邊來連接 G 的 所有頂點,則稱 G’ 為 G 的 擴張樹 擴張樹的特徵 非唯一 任兩頂點間均有路徑相通 共有 n-1 個邊,再加任何原圖 G 的其他非 G’ 的邊都會形成迴路. 1. 1. 擴張樹範例 1. 2. 2. 擴張樹範例 2. 這部份沒有範例程式,大家可以想想看要怎麼做. 以 DFS 拜訪頂點所得之擴張樹,但這裡與 7.4 不同的是 還須處理邊.
E N D
7.5 擴張樹 (Spanning Tree) • 一個無向相連圖 G 的子圖 G’ 如果可用最少的邊來連接G 的 • 所有頂點,則稱 G’ 為 G 的擴張樹 • 擴張樹的特徵 • 非唯一 • 任兩頂點間均有路徑相通 • 共有 n-1 個邊,再加任何原圖 G 的其他非 G’的邊都會形成迴路 1 1
擴張樹範例 1 2 2
擴張樹範例 2 這部份沒有範例程式,大家可以想想看要怎麼做 以 DFS 拜訪頂點所得之擴張樹,但這裡與 7.4 不同的是還須處理邊 以 BFS 拜訪頂點所得之擴張樹,但這裡與 7.4 不同的是還須處理邊 3 3
網路 (Network) 與最少成本擴張樹 (Minimum Cost Spanning Tree) • 如果在圖形 G的邊上賦予成本 (cost,又稱權重),得到的結果圖形就稱為網路 (Network) • 這個權重可以用之前的 2 維相鄰矩陣來存放 • 代表兩頂點 x, y不相鄰的方式有 2 種 • adjmatrix[x][y] = 0 :適用於 DFS, BFS 等應用 • adjmatrix[x][y] = ∞:適用於最少成本擴張樹 • 這個權重可用來代表 • 地圖上兩點間的距離、兩點間的行車時間、兩點間的成本… • 網路G的最少成本擴張樹是 G 的所有擴張樹中其邊的成本總和最低者 • 最少成本擴張樹非唯一 • 最少成本擴張樹任兩點 x, y間只有一條路徑,且此路徑之所有邊成本和不一定是 x, y間之最低成本 4
最小成本擴張樹範例 5 5
7.5.1 最小成本擴張樹- P氏法 (Prim’s Method) • P 氏法求 G=(V,E)之最小成本擴張樹 • 以頂點為導向,先確定要加進來的頂點,再由點找邊 • 將所有頂點切割成 X, Y兩個集合, X 用來代表還未加入最小成本擴張樹的頂點之集合, Y 用來代表已加入最少成本擴張樹的頂點之集合,令 T代表最小成本擴張樹 (含頂點及邊), P 氏法會將頂點一個一個由集合 X搬到 Y,直到 X 為空集合為止 1.令 X=V,Y=Φ,T=Φ (T 為空樹)。 2.從 X中任選一個頂點 x,將之從 X搬移到 Y,並將 x加入 T。 3.重覆執行步驟 4、5,一直到X為空集合為止 4. 從所有邊的集合 E中找出一條連接 X和 Y的最少成本邊 (x,y),其中 x ∈ X,y ∈ Y,且邊(x,y)加到 T不會造成迴路。 5. 將頂點 x自 X搬移到 Y,並將頂點 x與 邊(x,y)加入樹T。 6. 輸出最小成本擴張樹 T 及總成本。 • 範例:上一頁講義,假設步驟 2 選到的頂點為 a 6 6
練習 由 A 開始求 最小成本擴張樹 參考:http://students.ceid.upatras.gr/~papagel/project/prim.htm 7
7.5.2 最小成本擴張樹- K 氏法 (Kruskal’s Method) • K 氏法求 G=(V,E)之最小成本擴張樹 • 以邊為導向,慢慢將不會造成迴路且成本最小的邊加入最小成本擴張樹T,直到 T 的邊的個數為 n -1 1.令 T=Φ (T 為空樹)。 2.重覆執行步驟 3、4,一直到 T 的邊總數為n -1 3.從 E 中選取成本最小的邊(x ,y)。 4.如果將 (x,y) 加到 T 不會造成迴路,則 { 從E 中刪除邊 (x,y) , 將邊(x,y) 加到 T。 }否則 { 從E 中刪除邊 (x,y) } 5. 輸出最小成本擴張樹 T 及總成本。 • 範例:如 P 氏法2 個範例,再用K 氏法做一遍 (ch7_mincostspanningtree.java,有修正過) 跳過 7.5.3 參考:http://students.ceid.upatras.gr/~papagel/project/kruskal.htm
7.6 最短路徑問題 (shortest path problem) • 求得網路 G=(V,E) 的最小成本擴張樹並無法解決以下問題 • 單一頂點到其他頂點的最短距離(或最小成本)為何 • G 中任兩頂點間的最短距離(或最小成本)為何 • 本節改以有向圖為範例 9 9
7.6.1單一頂點到其他頂點的最短距離 • Dijkstra’s Algorithm:使用到 3 個陣列 • cost[n,n]:兩頂點間相鄰成本陣列成本 • 一開始對所有頂點 i, cost[i, i] = 0 • visited[n]:用來對已拜訪過的頂點做 “已拜訪” 的記號 • 一開始對所有頂點 i, visited[i] = false • dist[n] :存放出發頂點 s 到所有頂點到目前為止之最短距離 • 一開始 dist[i] = cost[s][i] (其中dist[s] = cost[s,s] = 0) • 變數 vcount 用來代表到目前為止拜訪過的頂點個數 10 10
∈ ∉ visited[s] 判斷加入 x 以後是否由 s 到 x 再到 i的距離會比現有最短距離還小 11
單一頂點到其他頂點的最短距離範例 12 12
ch7_shortestpath.java 練習:將 ch7_shortestpath.java 改為請使用者輸入出發的頂點 13 13
練習 14 14
練習參考解答 • 頂點0到其餘頂點之最短距離選取過程 • 頂點0到其餘頂點之最短路徑和距離 15 15
7.6.2 任兩頂點間的最短距離 (Floyd’s Algorithm) • 可用 7.6.1 的方法,輪流將各頂點設為出發頂點求得,但速度太慢 • 此節介紹可同時求得任兩頂點間的最短距離的方法 • 資料結構 • cost[n,n]:兩頂點間相鄰成本陣列成本 • 視題目有沒有要求一定要走出去,決定要不要 一開始對所有頂點 i, cost[i, i] = 0 • C[n][n]:存放到目前為止兩頂點間的最短距離 • C[n][n] 會慢慢改變,假設其改變順序為 C0[n][n], C1[n][n], …, Cn-1[n][n] 令各 Ck [i][j] 代表由頂點 i 到頂點 j 且所經過之頂點不超過k 的所有路 徑之最短距離,則當 k=n-1 時, Cn-1 [i][j] 代表由頂點 i 到頂點 j 且所經過之頂點不超過 n-1 的所有路徑之最短距離,也就是頂點 i 到頂點 j 的最短距離 (因為頂點編號是由 0 到 n-1) 課本 p.7-102 要訂正 16
演算法 (ch7_allpath.java) • 步驟 • 令 C-1[i][j]=cost[i][j] 對所有 i, j • for (k = 0; k <= n-1, k++) { Ck[i][j]= min{Ck-1[i][j] , Ck-1[i][k] + Ck-1[k][j] } } ∈ ∉ 17
範例 題目有要求一定要走出去 18
練習 題目沒要求一定要走出去 19
7.7 工作網路與拓樸排序(Topological Sort) • 頂點工作網路(Activity On Vertex Network),簡稱 AOV 網路 • 是一個有向圖 • 以頂點來代表工作項目 • 邊則用來代表工作被執行的優先順序 • 此圖不可有迴路 • 如果存在邊 <i,j>,表示 i工作須比 j工作早完成 (優先) • 拓樸排序:維持 AOV網路上各頂點之先後關係並依工作項目完成之先後加以排序 • 非唯一 20
拓樸排序範例 • 拓樸排序結果為 • A、B、C、D、E或 • B、A、C、D、E。 拓樸排序結果為 1、0、2、3、4 、5、6、7或 0、1、2、3、4 、6、5、7或 1、0、3、2、4 、5、6、7或 0、1、3、2、4 、5、6、7 或 1、0、2、3、4 、6、5、7 或 … 共 8 組 定義:拓樸排序的長度 為該排序所有路徑 之長度中的最大值 21
拓樸排序程式 (ch7_topologicalsort.java) • 當 AOV 網路尚有頂點,重複執行 2 2. 任意挑選一個 沒有先行者 (predecessor) 的頂點 x ,從 AOV 網路中刪除 x 以及從 x 出發的邊,輸出 x 22
以佇列實作拓樸排序程式(作業) ch7_topologicalsort.java 是依照頂點的號碼來找到一組 拓樸排序,以佇列實作可找到長度為最小的拓樸排序 (p.21) 令 counter =0 ; // 這用來紀錄已加入拓樸排序的頂點數目 • 先計算每一個頂點的入分支度 • 將入分支度為 0 的所有頂點加入一個 佇列 q • 執行以下動作,直到佇列為空 • 由佇列取出最前面的頂點 x ,並輸出 x • counter++; • 對所有 x 可連接到的頂點 y,如果 y還沒被輸出,進行以下動作: 將 y 的入分支度減 1,如果 y 的入分支度成為 0 ,則將 y加入佇列 q 4. 如果 counter < n ,表示該 有向圖 有迴路
ch7_mincostspanningtree.java 的問題 > 演算法是正確,但是 cycle( ) 的判斷有問題,以下例來看: 將 (0,1), (3,4) 加入 T 後,接下來 cycle( ) 會 判斷 (0,3) 造成迴路, 再判斷 (1,3) 也造成迴路,於是選擇 (4,5) 結果是錯的
修正 ch7_mincostspanningtree.java 中cycle 的做法 • 概念:於運算過程中,維護各相連子圖的代表頂點,如果要加進來的邊的兩個頂點所在之相連子圖的代表頂點相同,則表示有迴路 • 作法:以相連子圖所有頂點中數字最小的頂點代表作為該相連子圖之代表頂點 • 設計一個陣列 represent[n],此陣列用來代表各頂點目前所屬相連子圖的代表頂點,由於剛開始的時候,各頂點都沒有加入 represent[i]的值就是 i • 最小成本邊選好以後,假設該邊為 (x,y) • 如果 represent[x] = represent[y],則加入此邊會造成迴路 • 如果 represent[x] ≠ represent[y],則加入此邊不會造成迴路,而可連接原來不相鄰的子圖 • 假設 represent[x] 與 represent[y] 的較小值為 z1 、較大值為 z2,則檢查所有 represent[i] 的值,如果其值為 z2,就將之改為 z1
作業 3 • 完成 最小成本擴張樹- P氏法 此題請由檔案輸入該網路的成本矩陣 2. 完成最小成本擴張樹- K 氏法正確的cycle方法 (投影片第 25 頁) 3. ch7_topologicalsort.java 是依照頂點的號碼來找到一組 拓樸排序,本題要求如第 23 頁的演算法改寫 ch7_topologicalsort.java。 此題請由檔案輸入該有向圖的相鄰矩陣。 27