資料結構 第16講 溝通無限校園網——最小生成樹(prim演算法)
本內容來源於本人著作《趣學演算法》,線上章節:http://www.epubit.com.cn/book/details/4825
校園網是為學校師生提供資源共享、資訊交流和協同工作的計算機網路。校園網是一個寬頻、具有互動功能和專業性很強的區域網絡。如果一所學校包括多個學院及部門,也可以形成多個區域網絡,並通過有線或無線方式連線起來。原來的網路系統只侷限於以學院、圖書館為單位的區域網,不能形成集中管理以及各種資源的共享,個別學院還遠離大學本部,這些情況嚴重地阻礙了整個學校的網路化需求。現在需要設計網路電纜佈線,將各個單位的區域網絡連通起來,如何設計能夠使費用最少呢?
圖2-58 校園網路
2.7.1 問題分析
某學校下設10個學院,3個研究所,1個大型圖書館,4個實驗室。其中,1~10號節點代表10個學院,11~13號節點代表3個研究所,14號節點代表圖書館,15~18號節點代表4個實驗室。該問題用無向連通圖G =(V,E)來表示通訊網路,V表示頂點集,E表示邊集。把各個單位抽象為圖中的頂點,頂點與頂點之間的邊表示單位之間的通訊網路,邊的權值表示佈線的費用。如果兩個節點之間沒有連線,代表這兩個單位之間不能佈線,費用為無窮大。如圖2-59所示。
圖2-59 校園網連通圖
那麼我們如何設計網路電纜佈線,將各個單位連通起來,並且費用最少呢?
對於n
需要說明幾個概念。
(1)子圖:從原圖中選中一些頂點和邊組成的圖,稱為原圖的子圖。
(2)生成子圖:選中一些邊和所有頂點組成的圖,稱為原圖的生成子圖。
(3)生成樹:如果生成子圖恰好是一棵樹,則稱為生成樹。
(4)最小生成樹:權值之和最小的生成樹,則稱為最小生成樹。
本題就是最小生成樹求解問題。
2.7.2 演算法設計
找出n−1條權值最小的邊很容易,那麼怎麼保證無迴路呢?
如果在一個圖中深度搜索或廣度搜索有沒有迴路,是一件繁重的工作。有一個很好的辦法——避圈法
首先任選一個結點,例如1號結點,把它放在集合U中,U={1},那麼剩下的結點即V−U={2,3,4,5,6,7},V是圖的所有頂點集合。如圖2-60所示。
圖2-60 最小生成樹求解過程
現在只需在連線兩個集合(V和V−U)的邊中看哪一條邊權值最小,把權值最小的邊關聯的結點加入到集合U。從圖2-68可以看出,連線兩個集合的3條邊中,結點1到結點2的邊權值最小,選中此條邊,把2號結點加入U集合U={1,2},V−U={3,4,5,6,7}。
再從連線兩個集合(V和V−U)的邊中選擇一條權值最小的邊。從圖2-61可以看出,連線兩個集合的4條邊中,結點2到結點7的邊權值最小,選中此條邊,把7號結點加入U集合U={1,2,7},V−U={3,4,5,6}。
圖2-61 最小生成樹求解過程
如此下去,直到U=V結束,選中的邊和所有的結點組成的圖就是最小生成樹。
是不是非常簡單啊?
這就是Prim演算法,1957年由美國電腦科學家Robert C.Prim發現的。那麼如何用演算法來實現呢?
首先,令U={u0},u0∈V,TE={}。u0可以是任何一個結點,因為最小生成樹包含所有結點,所以從哪個結點出發都可以得到最小生成樹,不影響最終結果。TE為選中的邊集。
然後,做如下貪心選擇:選取連線U和V−U的所有邊中的最短邊,即滿足條件i∈U,j∈V−U,且邊(i,j)是連線U和V−U的所有邊中的最短邊,即該邊的權值最小。
然後,將頂點j加入集合U,邊(i,j)加入TE。繼續上面的貪心選擇一直進行到U=V為止,此時,選取到的所有邊恰好構成圖G的一棵最小生成樹T。
演算法設計及步驟如下。
步驟1:確定合適的資料結構。設定帶權鄰接矩陣C儲存圖G,如果圖G中存在邊(u,x),令C[u][x]等於邊(u,x)上的權值,否則,C[u][x]=∞;bool陣列s[],如果s[i]=true,說明頂點i已加入集合U。
如圖2-62所示,直觀地看圖很容易找出 U 集合到 V−U集合的邊中哪條邊是最小的,但是程式中如果窮舉這些邊,再找最小值就太麻煩了,那怎麼辦呢?
圖2-62 最小生成樹求解過程
可以通過設定兩個陣列巧妙地解決這個問題,closest[j]表示V−U中的頂點j到集合U中的最鄰近點,lowcost[j]表示V−U中的頂點j到集合U中的最鄰近點的邊值,即邊(j,closest[j])的權值。
例如,在圖2-62中,7號結點到U集合中的最鄰近點是2,closest[7]=2,如圖2-63所示。7號結點到最鄰近點2的邊值為1,即邊(2,7)的權值,記為lowcost[7]=1,如圖2-64所示。
圖2-63 closest[]陣列
圖2-64 lowcost[]陣列
只需要在V−U集合中找lowcost[]值最小的頂點即可。
步驟2:初始化。令集合U={u0},u0∈V,並初始化陣列closest[]、lowcost[]和s[]。
步驟3:在V−U集合中找lowcost值最小的頂點t,即lowcost[t]=min{lowcost[j]|j∈V−U},滿足該公式的頂點t就是集合V−U中連線集合U的最鄰近點。
步驟4:將頂點t加入集合U。
步驟5:如果集合V−U為空,演算法結束,否則,轉步驟6。
步驟6:對集合V−U中的所有頂點j,更新其lowcost[]和closest[]。更新公式:if(C[t] [j]<lowcost [j] ) { lowcost [j]= C [t] [j]; closest [j] = t; },轉步驟3。
按照上述步驟,最終可以得到一棵權值之和最小的生成樹。
2.7.3 完美圖解
設G =(V,E)是無向連通帶權圖,如圖2-65所示。
圖2-65 無向連通帶權圖G
(1)資料結構
設定地圖的帶權鄰接矩陣為C[][],即如果從頂點i到頂點j有邊,就讓C[i][j]=<i,j>的權值,否則C[i][j]=∞(無窮大),如圖2-66所示。
圖2-66 鄰接矩陣C[ ][ ]
(2)初始化
假設u0=1;令集合U={1},V−U={2,3,4,5,6,7},TE={},s[1]=true,初始化陣列closest[]:除了1號結點外其餘結點均為1,表示V−U中的頂點到集合U的最臨近點均為1,如圖2-67所示。lowcost[]:1號結點到V−U中的頂點的邊值,即讀取鄰接矩陣第1行,如圖2-68所示。
圖2-67 closest[]陣列
圖2-68 lowcost[]陣列
初始化後如圖2-69所示。
圖2-69 最小生成樹求解過程
(3)找最小
在集合V−U={2,3,4,5,6,7}中,依照貪心策略尋找V−U集合中lowcost最小的頂點t,如圖2-70所示。
圖2-70 lowcost[]陣列
找到最小值為23,對應的結點t=2。
選中的邊和結點如圖2-71所示。
圖2-71 最小生成樹求解過程
(4)加入U戰隊
將頂點t加入集合U={1,2},同時更新V−U={3,4,5,6,7}。
(5)更新
剛剛找到了到U集合的最鄰近點t = 2,那麼對t在集合V−U中每一個鄰接點j,都可以藉助t更新。我們從圖或鄰接矩陣可以看出,2號結點的鄰接點是3和7號結點:
C[2][3]=20<lowcost[3]=∞,更新最鄰近距離lowcost[3]=20,最鄰近點closest[3]=2;
C[2][7]=1<lowcost[7]=36,更新最鄰近距離lowcost[7]=1,最鄰近點closest[7]=2;
更新後的closest[j]和lowcost[j]陣列如圖2-72和圖2-73所示。
圖2-72 closest[]陣列
圖2-73 lowcost[]陣列
更新後如圖2-74所示。
圖2-74 最小生成樹求解過程
closest[j]和lowcost[j]分別表示V−U集合中頂點j到U集合的最鄰近頂點和最鄰近距離。3號頂點到U集合的最鄰近點為2,最鄰近距離為20;4、5號頂點到U集合的最鄰近點仍為初始化狀態1,最鄰近距離為∞;6號頂點到U集合的最鄰近點為1,最鄰近距離為28;7號頂點到U集合的最鄰近點為2,最鄰近距離為1。
(6)找最小
在集合V−U={3,4,5,6,7}中,依照貪心策略尋找V−U集合中lowcost最小的頂點t,如圖2-75所示。
圖2-75 lowcost[]陣列
找到最小值為1,對應的結點t=7。
選中的邊和結點如圖2-76所示。
圖2-76 最小生成樹求解過程
(7)加入U戰隊
將頂點t加入集合U={1,2,7},同時更新V−U={3,4,5,6}。
(8)更新
剛剛找到了到U集合的最鄰近點t =7,那麼對t在集合V−U中每一個鄰接點j,都可以借t更新。我們從圖或鄰接矩陣可以看出,7號結點在集合V−U中的鄰接點是3、4、5、6結點:
C[7][3]=4<lowcost[3]=20,更新最鄰近距離lowcost[3]=4,最鄰近點closest[3]=7;
C[7][4]=9<lowcost[4]=∞,更新最鄰近距離lowcost[4]=9,最鄰近點closest[4]=7;
C[7][5]=16<lowcost[5]=∞,更新最鄰近距離lowcost[5]=16,最鄰近點closest[5]=7;
C[7][6]=25<lowcost[6]=28,更新最鄰近距離lowcost[6]=25,最鄰近點closest[6]=7;
更新後的closest[j]和lowcost[j]陣列如圖2-77和圖2-78所示。
圖2-77 closest[]陣列
圖2-78 lowcost[]陣列
更新後如圖2-79所示。
圖2-79 最小生成樹求解過程
closest[j]和lowcost[j]分別表示V−U集合中頂點j到U集合的最鄰近頂點和最鄰近距離。3號頂點到U集合的最鄰近點為7,最鄰近距離為4;4號頂點到U集合的最鄰近點為7,最鄰近距離為9;5號頂點到U集合的最鄰近點為7,最鄰近距離為16;6號頂點到U集合的最鄰近點為7,最鄰近距離為25。
(9)找最小
在集合V−U={3,4,5,6}中,依照貪心策略尋找V−U集合中lowcost最小的頂點t,如圖2-80所示。
圖2-80 lowcost[]陣列
找到最小值為4,對應的結點t=3。
選中的邊和結點如圖2-81所示。
圖2-81 最小生成樹求解過程
(10)加入U戰隊
將頂點t加入集合U ={1,2,3,7},同時更新V−U={4,5,6}。
(11)更新
剛剛找到了到U集合的最鄰近點t =3,那麼對t在集合V−U中每一個鄰接點j,都可以藉助t更新。我們從圖或鄰接矩陣可以看出,3號結點在集合V−U中的鄰接點是4號結點:
C[3][4]=15>lowcost[4]=9,不更新。
closest[j]和lowcost[j]陣列不改變。
更新後如圖2-82所示。
相關推薦
資料結構 第16講 溝通無限校園網——最小生成樹(prim演算法)
本內容來源於本人著作《趣學演算法》,線上章節:http://www.epubit.com.cn/book/details/4825 校園網是為學校師生提供資源共享、資訊交流和協同工作的計算機網路。校園網是一個寬頻、具有互動功能和專業性很強的區域網絡。如果一所學校包括多個學院及部門,也可
資料結構 第17講 溝通無限校園網——最小生成樹(kruskal演算法)
本內容來源於本人著作《趣學演算法》,線上章節:http://www.epubit.com.cn/book/details/4825 構造最小生成樹還有一種演算法,Kruskal演算法:設G=(V,E)是無向連通帶權圖,V={1
資料結構實驗之圖論九:最小生成樹 (SDUT 2144)
#include<bits/stdc++.h> using namespace std; typedef long long ll; struct node { int s, e; int w; }s[100005]; int c[105]; bool cmp(str
資料結構——第四章圖:04最小生成樹
1.(連通網的)最小生成樹問題提出:假設要在n個城市之間建立通訊聯絡網,則連通n個城市只需要修建n-1條線路,如果在最節省經費的前提下建立這個通訊網?該問題等價於:構造網的一棵最小生成樹,即:在e條帶權的邊中選取n-1條邊(不構成迴路),使權值之和為最小。有兩種演算法:Prim(普利姆)演算法和Kruskal
NYOJ - 溝通無限校園網(最小生成樹)
題目連結:http://nyoj.top/problem/1403 記憶體限制:64MB 時間限制:1000ms 題目描述: 校園網是為學校師生提供資源共享、資訊交流和協同工作的計算機網路。校園網是一個寬頻、具有互動功能和專業性很強的區域網絡。如果一所學校包括多個
資料結構 筆記:最小生成樹(prim)
運營商的挑戰 -在下圖標出的城市間架設一條通訊線路 要求: ·任意兩個城市間都能夠通訊 ·將架設成本呢將至最低 如何在圖中選擇n-1條邊使得n個頂點間兩兩可達,並且這n-1條邊的權值之和最小 最小生成樹 -僅使用圖中的n-1條邊連線圖中的n個頂點
資料結構實驗之圖論九:最小生成樹__Prim
Problem Description 有n個城市,其中有些城市之間可以修建公路,修建不同的公路費用是不同的。現在我們想知道,最少花多少錢修公路可以將所有的城市連在一起,使在任意一城市出發,可以到達其他任意的城市。 Input 輸入包含多組資料,格式如下。 第一行包括兩個整數n m,
(c++)資料結構與演算法之圖:鄰接矩陣、深度廣度遍歷、構造最小生成樹(prim、kruskal演算法)
//圖的鄰接矩陣實現 //廣度遍歷bfs和深度遍歷dfs //構造最小生成樹的prim、kruskal演算法 #include <iostream> #include<stack> #include<queue> #define WEI
資料結構 第14講 神祕電報密碼——哈夫曼編碼
本文來源於本人著作《趣學演算法》。 看過諜戰電影《風聲》的觀眾都會對影片中神奇的訊息傳遞驚歎不已!吳志國大隊長在受了殘忍的“針刑”之後躺在手術檯上唱空城計,變了音調,把訊息傳給了護士,顧曉夢在衣服上縫補了長短不一的針腳……那麼,片中無處不在的摩爾斯碼到底是什麼?它又有著怎樣的神祕
第 16 章 C 預處理器和 C 庫(條件編譯)
struct FN getc con ade 定義 輸入 lap pla 1 /*-------------------------------------- 2 names_st.h -- names_st 結構的頭文件 3 --------------
【資料結構】二叉樹的建立與遍歷(遞迴)
該程式全是使用遞迴的操作 執行環境是:Dev-C++ #include <stdio.h> #include <stdlib.h> typedef struct node{ char data; struct node *lchild,*rchild; }bi
資料結構實驗之棧與佇列四:括號匹配(SDUT 2134)
#include <bits/stdc++.h> using namespace std; typedef long long ll; char s[100]; char a[100]; int main() { int i,j,k,f,top,len; while(
資料結構——圖(8)——最小生成樹(MST)
問題的提出 如下圖,假設這裡有一系列的房屋,問如何鋪設電線,可以使得連線所有房屋的電線的總成本最低?這是20世紀20年代早期研究最小生長樹的最初動機。 (捷克數學家OtakarBorůvka完成的工作)。 最短路徑樹與最小生成樹(MST) 上次,我們看到了Dijkstra演
資料結構實現 5.1:對映_基於樹實現(C++版)
資料結構實現 5.1:對映_基於樹實現(C++版) 1. 概念及基本框架 2. 基本操作程式實現 2.1 增加操作 2.2 刪除操作 2.3 修改操作 2.4 查詢操作 2.5 其他操作 3. 演算法複
資料結構實驗之二叉樹七:葉子問題(SDUT 3346)
#include <bits/stdc++.h> using namespace std; struct node { char data; struct node *lc, *rc; }; char a[100]; int num = 0; struct node
資料結構 筆記:最小生成樹(Kruskal)
最小生成樹的特徵: -選取的邊是圖中權值較小的邊 -所有邊連線後不構成迴路 既然最小生成樹關心的是如何選擇n-1條邊,那麼是否可以直接以邊為核心進行演算法設計? -由4個頂點構成圖,選擇3條權值最小的邊 如何判斷新選擇的邊與已選擇的邊是否構成迴路? 技巧:前驅標記陣列 -
最小生成樹(資料結構)
最小生成樹-Prim演算法和Kruskal演算法 Prim演算法 1.概覽 普里姆演算法(Prim演算法),圖論中的一種演算法,可在加權連通圖裡搜尋最小生成樹。意即由此演算法搜尋到的邊子集所構成的樹中,不但包括了連
中國大學MOOC-陳越、何欽銘-資料結構-2018秋 03-樹1 樹的同構 (25 分)
給定兩棵樹T1和T2。如果T1可以通過若干次左右孩子互換就變成T2,則我們稱兩棵樹是“同構”的。例如圖1給出的兩棵樹就是同構的,因為我們把其中一棵樹的結點A、B、G的左右孩子互換後,就得到另外一棵樹。而圖2就不是同構的。 圖1 圖2 現給定兩棵樹,請你判
浙大版《資料結構》習題4.3 是否二叉搜尋樹 (25 分)
本題要求實現函式,判斷給定二叉樹是否二叉搜尋樹。 函式介面定義: bool IsBST ( BinTree T ); 其中BinTree結構定義如下: typedef struct TNode *Position; typedef Position BinT
資料結構實驗之查詢一:二叉排序樹 (SDUT 3373)
二叉排序樹(Binary Sort Tree),又稱二叉查詢樹(Binary Search Tree),也稱二叉搜尋樹。 #include <stdio.h> #include <string.h> #include <stdlib.h> struct nod