最小生成樹(kruskal)

2022-05-02 06:45:10 字數 2463 閱讀 6057

先來前排賣個瓜子,推薦個oj:乙個神奇的oj

假設要在n個城市之間建立通訊聯絡網,則連通n個城市只需要n-1條線路。

這時, 如何在最節省經費的前提下建立這個通訊網。

在每兩個城市之間都可以設定—條線路,相應地都要付出一定的經濟代價。

n個城市之間,最多可能設定n(n- 1)/2條線路,那麼,如何在這些可能的線路中選擇n-1條,以使總的耗費最少呢?

這題是裸的最小生成樹,何為最小生成樹?就是一張圖,n個點,n-1條邊,且邊上的權值加起來還要最小

這題的樣例圖如下

(畫圖技術不要吐槽)

這圖的最小生成樹就是

邊上的權值相加就是75,就是最小生成樹了

那麼怎麼知道是這樣一棵樹呢

最小生成樹有兩個做法

1.prim

2.克魯斯卡(英語不行)

我的做法是克魯斯卡的

克魯斯卡的做法就是:

首先是排序邊:

然後將並查集所需要的f陣列初始化

這裡需要自行去查詢並查集的寫法

選取最小的邊,也就是第一條

第一條邊所連線的兩個點是1,2

用並查集查詢1和2的祖先

u=find(1),v=find(2)

發現u不等於v,我們就把他們並在一起即f[v]=u,這樣下次查詢祖先就可以找到同乙個了

然後仿照剛剛的做法就可以把2和5也連線起來

但這裡要記得是把f[5]賦值為2的祖先,即1

3和5的這一條也不多說的,直接上圖

3和4,4和6的這兩條也來了(唉,,圖好多,,這是我畫得最好的圖了)

至此,一棵完美的最小生成樹就完成了

比如到了2和3這一條

此時按照剛剛的步驟,它會先找2的祖先u=3,再找3的祖先v=3

這時我們發現兩點已經連通,沒必要再連一次了,所以就不會連了

也就是說判斷是否連通只要判斷u是否等於v

另外咱們選的邊是從最小開始的選取,所以生成的樹自然也就是最小的

用一句話概括:易證其正確性

所以我就不證了,剩下的內容自己腦補吧

如果前面都看懂了,那麼恭喜你學會了最小生成樹,等你**寫多了,你就會發現

這個演算法其實並沒有什麼卵用,,,感覺很少用到的樣子

要想考試拿高分,還得學爆搜啊:)

1 #include 2 #include 3 #include 4 #include 5

using

namespace

std;

6int f[300];7

struct

graph

8a[45000

];11

bool

cmp(graph x,graph y)

1215

int find(int

x)16

19int

main()

2036

}37 sort(a+1,a+k,cmp);

38for(i=1;i)

3947

}48 printf("

%d\n

",ans);

49return0;

50 }

69 通訊線路

kruskal 最小生成樹

include include 產生隨機數組用 include 同上 include using namespace std 1 帶權邊的類myarc class myarc bool operator const myarc arc myarc myarc int beginvex,int end...

最小生成樹Kruskal

最小生成樹有兩個特點,乙個是保證了所有邊的和是最小值,另乙個是保證了所有邊中的最大值最小。struct edge bool friend operator edge a,edge b 構邊 vectoredge int id max int mini void initial void input ...

最小生成樹(kruskal)

kruskal演算法 1 記graph中有v個頂點,e個邊 2 新建圖graphnew,graphnew中擁有原圖中相同的e個頂點,但沒有邊 3 將原圖graph中所有e個邊按權值從小到大排序 4 迴圈 從權值最小的邊開始遍歷每條邊 直至圖graph中所有的節點都在同乙個連通分量中 if 這條邊連線...