【圖論】最小產生樹

來源:互聯網
上載者:User
最小產生樹的概念

目的: 對於n個節點以及m條帶有權重邊的連通圖, 切掉若干條邊,使得剩餘的邊的權重和最小並且該圖是一顆樹(即含有n個節點以及n-1條邊的連通子圖) 為什麼需要最小產生樹

如果把邊的權重看成是串連兩個節點所需要的cost,那麼最小產生樹就可以使得原圖的各個節點仍舊保持互連的狀態,並且cost最小。其本質是一個最佳化的問題。 Kruskal演算法的基本思想

核心本質是逆向思維。你不是讓我去掉某些邊嗎。那麼我索性把所有邊都去掉,然後從權重小的邊開始一條一條加回來。每加回一條邊,就會使兩個節點連通,如果這兩個節點本身就是連通的,那麼這一條邊就不要加回來,如果這兩個節點本身是不連通的,那麼這一條邊就需要加回來。最後加回來的邊數到達節點數減1的時候,就是一顆最小產生數了。

虛擬碼如下:

node_list = [a,b,c,d] // 所有節點的數組tree_list = [{a}, {b}, {c}, {d}] // 所有獨立的樹的數組,由於一開始去掉了所有的邊,所以a,b,c,d四個節點都變成孤立的單節點樹,最終目的是通過加邊,使得tree_list逐漸層為[{a, b}, {c}, {d}] => [{a, b}, {c, d}] => [{a, b, c, d}]。edge_list = [e1, e2, e3, e4, e5] // 所有邊的容器selected_edge_list = [] // 挑選的邊的結果數組,一開始為空白while length(selected_edge_list) < length(node_list) - 1: // 最終需要挑選出n-1條邊,因為一棵樹是n-1條邊    // 每次從邊的容器中pop出一個最小的權重的邊    min_edge = get_and_pop_min_edge(edge_list)    // 檢查min_edge的兩端節點在tree_list中是否處於兩顆樹中,如果是的話,就可以連通這兩顆樹    if can_merge_tree(tree_list, min_edge) is True:        tree_list = merge_tree(tree_list, min_edge)        selected_edge_list.append(min_edge)return selected_edge_list
Prim演算法的基本思想

Prim的演算法的本質是加點法。先隨機挑選一個點作為最小產生樹A中的起始點,其他點作為候選點。每次從候選點集合裡面選擇一個到達樹A的距離最短的點並把這個點和這個點到樹A的一邊加入到最小產生樹A中去(即每次加一點一邊)。直到最小產生樹A包含了所有的點。

這個演算法比較容易理解,虛擬碼略。 注意

很明顯,Kruskal和Prim演算法都是通過貪心的尋找局部最優來解題。但是你要記住局部最優的方案並不一定是全域最優的。當然在最小產生樹的問題上,Kruskal和Prim演算法都已經被證明了這樣的演算法是可以全域最優的。 時間複雜度

Prim演算法的時間複雜度為O(n2),與網中的邊數無關,適合於稠密圖(即邊多點少);而Kruskal的演算法複雜度為O(elog e),與網中的邊數有關,適合於稀疏圖(即點多邊少)。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.