日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

图论(九)最小生成树-Kruskal算法

發(fā)布時間:2025/3/20 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 图论(九)最小生成树-Kruskal算法 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前面說過Kruskal是從最短邊著手構建最小生成樹的。其基本過程是:先對圖中的所有邊按照權重值從小到大進行排序,然后著手選取邊構建最小生成樹。如果直接從小到大按順序選取,有可能形成了環(huán),所以對環(huán)的處理就成了核心問題。


我們還是以前面的鄉(xiāng)鎮(zhèn)假設光纖網(wǎng)絡為例:

Kruskal算法工作步驟如下:

(1)?邊進行排序。

Begin

End

Weight

e

i

7

c

h

8

a

b

10

a

f

11

b

g

12

b

h

12

d

i

16

f

g

17

b

d

18

g

i

19

d

e

20

d

h

21

c

d

22

d

g

24


(2)?權重依次從小到大加入最小生成樹。

?

我們依次將邊e-i(7),c-h(8),a-b(10),a-f(11),b-g(12),b-h(12),d-i(16)加入最小生成樹中(圖中標綠色的邊),到目前為止,沒有任何問題。


(3)?檢查新加入的邊是否構成了環(huán)。

下面,按照順序需要將邊f-g(17)加入最小生成樹。

?

很不幸,這時a-b-g-f-a構成了環(huán)。于是f-g(17)被排除,不能被加入最小生成樹。


下面按順序加入的邊是b-c(18),同樣b-c-g-b也構成了環(huán),所以邊b-c(18)也被排除。如此依次類推,最后得到的最小生成樹是:

?

好了,算法介紹完了。就這么簡單

?

當然,這里有個核心問題還沒有清楚的描述,即怎樣判斷構成了環(huán)?


判斷原理也很簡單:最小生成樹加入一條邊從而構成環(huán),那么這條兩個頂點除了這條邊外,必然有另一條路徑,即兩個頂點在加入這個邊之前,就是連通的或者在一個連通子圖上。


因此,在G=(V,E),我們令最小生成樹初始狀態(tài)為只有n個頂點,0邊的非連通圖T=(V,{})圖中每個頂點都是一個連通子圖n個連通子圖。依次E按順序從小到大選擇邊,該邊的兩個頂點落在T不同的連通子圖上,則將次變加入到T,否則舍去此邊,依次類推,直到T所有頂點都在同一個連通子圖上為止


光說不練假把式。上代碼:

# -*- coding: utf-8 -*-

# 構建圖G,使用了鄰接矩陣表示法,9999代表非直連
G =[[0,10,9999,9999,9999,11,9999,9999,9999], ?# a的鄰居表
?????[10,0,18,9999,9999,9999,12,12,9999], ?# b的鄰居表
?????[9999,18,0,22,9999,9999,9999,8,9999], ?# c的鄰居表
?????[9999,9999,22,0,20,9999,24,21,16], ?# d的鄰居表
?????[9999,9999,9999,20,0,26,9999,9999,7], ?# e的鄰居表
?????[11,9999,9999,9999,26,0,17,9999,9999], ?# f的鄰居表
?????[9999,12,9999,24,9999,17,0,9999,19], ?# g的鄰居表
?????[9999,12,8,21,9999,9999,9999,0,9999], ?# h的鄰居表
?????[9999,9999,9999,16,7,9999,19,9999,0]] ?# i的鄰居表

# 構建頂點序號符號對應集
v_dict ={}
v_strdict ={}
v_str ='abcdefghi'
for iin range(len(G)):
????v_dict[i]= v_str[i]
for i, valuein enumerate(v_str):
????v_strdict[value]= i

# 構建邊集
E =[(v_dict[u], v_dict[v], G[u][v]) for uin range(len(G))for vin range(len(G[u]))if 0< G[u][v]< 9999and u< v]

# 對邊集進行排序
E =sorted(E,key=lambdax:x[2])

# 構建最小生成樹
T =set()

# 構建頂點連通子圖
V =[0]* len(G)

# 判斷是否屬于同一連通子圖
def find_connect(V,v):
????whileV[v]> 0:
????????v= V[v]
????returnv

# 循環(huán)邊
for ein E:
????#邊的兩個頂點是否已連通
????v1, v2= find_connect(V, v_strdict[e[0]]), find_connect(V, v_strdict[e[1]])
????ifv1 !=v2:
????????V[v1]= v2
????????T.add(e) #將邊加入最小生成樹

# 輸出最小生成樹
print(T)
# 輸出代價
print(sum([t[2]for tin T]))

?

輸出結果:

{('e', 'i', 7), ('g', 'i', 19), ('c', 'h', 8), ('a', 'f', 11), ('b', 'g', 12), ('d', 'i', 16), ('a', 'b', 10), ('b', 'h', 12)}

95

算法的主要執(zhí)行過程在最后的for循環(huán)處find_connect函數(shù)與頂點的個數(shù)V決定,時間復雜度為O(logV)而外面是邊E循環(huán),因此Kruskal算法的時間復雜度為O(E logV)

總結

以上是生活随笔為你收集整理的图论(九)最小生成树-Kruskal算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。