貪心算法之最小生成樹問題

1. 貪心算法的基本思想

貪心算法在每一步都選擇局部最優的邊,希望最終得到整體最優的生成樹。常見的兩種 MST 算法為 Kruskal 算法Prim 算法。這兩者均滿足貪心選擇性質和最優子結構性質,即:

  • 貪心選擇性質:局部最優選擇(比如選擇當前權值最小的邊)可以構成全局最優解。

  • 最優子結構:一個最優解包含其子問題的最優解。


2. 正確性證明

2.1 交換論證法

以 Kruskal 算法為例,正確性證明常使用“交換論證法”:

  • 假設在某一步選取了當前權值最小的邊 e,若該邊不在某最優解中,則存在一個邊 f(在最優解中)可以與 e 交換,并且不會增加生成樹的總權值。

  • 通過不斷的“交換”,最終可構造出與 Kruskal 算法選取的邊集合相同的生成樹,從而證明其最優性。

2.2 剪枝證明(Cut Property)

  • 割定理(Cut Property):對于圖中的任一割,跨割的最小邊必定屬于某個 MST。

  • Kruskal 算法每次選擇全圖中最小且不會形成環的邊,正好滿足割定理,從而確保了所選邊集一定可以擴展為 MST。

類似地,Prim 算法從任意一個點開始,每次添加連接已構造生成樹和其他頂點之間最小的邊,這也遵循割定理,從而保證了正確性。


3. 算法步驟

3.1 Kruskal 算法步驟

  1. 排序:將所有邊按權值從小到大排序。

  2. 初始化:每個頂點為一個獨立的集合(并查集數據結構)。

  3. 遍歷邊集:依次取出最小邊,判斷其兩個頂點是否在同一集合:

    • 如果不在同一集合,則將該邊加入生成樹,并合并兩個集合;

    • 否則,跳過該邊(避免環的產生)。

  4. 終止條件:當生成樹邊數達到 n?1(n 為頂點數)時結束。

3.2 Prim 算法步驟

  1. 初始化:任選一個頂點,將其加入 MST 集合。

  2. 維護優先隊列:將所有與當前生成樹相連的邊加入優先隊列。

  3. 選擇邊:從隊列中取出最小邊,若其另一端未被訪問,則加入生成樹,并將該頂點所有相連邊更新到隊列。

  4. 重復:直到所有頂點均已加入 MST。


4. 時間復雜度分析

4.1 Kruskal 算法

  • 排序:對所有 E 條邊進行排序,時間復雜度為 O(Elog?E) 。

  • 合并查找:利用路徑壓縮和按秩合并,合并與查詢的時間復雜度近似為 O(α(n))(α 為阿克曼函數的反函數,幾乎看作常數)。

  • 總體:總體時間復雜度為 O(Elog?E),當圖稀疏時可近似看作 O(Elog?V)。

4.2 Prim 算法

  • 利用最小堆:每次從堆中取出最小邊和更新堆的操作總體復雜度為 O((E+V)log?V)。

  • 總體:因此總體時間復雜度為 O(Elog?V)。


5. 實例分析

考慮下列圖:

  • 頂點集合:{A, B, C, D, E}

  • 邊集合及權值:

    • A-B: 1

    • A-C: 3

    • B-C: 3

    • B-D: 6

    • C-D: 4

    • C-E: 2

    • D-E: 5

利用 Kruskal 算法構造 MST:

  1. 排序邊:A-B(1), C-E(2), A-C(3), B-C(3), C-D(4), D-E(5), B-D(6)。

  2. 選邊

    • A-B (1):加入,集合合并 {A, B}。

    • C-E (2):加入,集合合并 {C, E}。

    • A-C (3):A 屬于 {A, B},C 屬于 {C, E},加入,集合合并 {A, B, C, E}。

    • B-C (3):跳過(形成環)。

    • C-D (4):D 未加入集合,加入后合并為 {A, B, C, D, E}。

  3. 完成:共選 4 條邊,即生成 MST,總權值 1+2+3+4=10。


6. Python代碼舉例

以下代碼使用 Kruskal 算法實現 MST 求解,并展示了如何使用并查集數據結構:

class UnionFind:def __init__(self, n):self.parent = list(range(n))self.rank = [0] * ndef find(self, u):if self.parent[u] != u:self.parent[u] = self.find(self.parent[u])return self.parent[u]def union(self, u, v):root_u = self.find(u)root_v = self.find(v)if root_u == root_v:return False  # u 和 v 已經在同一集合# 按秩合并if self.rank[root_u] < self.rank[root_v]:self.parent[root_u] = root_velif self.rank[root_u] > self.rank[root_v]:self.parent[root_v] = root_uelse:self.parent[root_v] = root_uself.rank[root_u] += 1return Truedef kruskal(n, edges):"""n: 頂點數,頂點編號為 0 到 n-1edges: 邊列表,每個元素 (u, v, weight)返回最小生成樹的邊列表及總權值"""# 按權值排序邊edges.sort(key=lambda x: x[2])uf = UnionFind(n)mst = []total_weight = 0for u, v, weight in edges:if uf.union(u, v):mst.append((u, v, weight))total_weight += weightif len(mst) == n - 1:breakreturn mst, total_weight# 示例數據
# 對應上面的實例,頂點 A,B,C,D,E 分別用 0,1,2,3,4 表示
edges = [(0, 1, 1),  # A-B(0, 2, 3),  # A-C(1, 2, 3),  # B-C(1, 3, 6),  # B-D(2, 3, 4),  # C-D(2, 4, 2),  # C-E(3, 4, 5)   # D-E
]
n = 5mst, total_weight = kruskal(n, edges)
print("最小生成樹邊集:", mst)
print("總權值:", total_weight)

運行結果將輸出 MST 邊集及其總權值。例如,上述代碼可能輸出:

最小生成樹邊集: [(0, 1, 1), (2, 4, 2), (0, 2, 3), (2, 3, 4)]
總權值: 10

最小生成樹邊集: [(0, 1, 1), (2, 4, 2), (0, 2, 3), (2, 3, 4)] 總權值: 10


總結

  • 邏輯推理與正確性證明:貪心算法基于割定理及交換論證法保證了局部最優選擇可推導出全局最優解。

  • 算法步驟:Kruskal 和 Prim 分別通過排序邊或維護最小堆實現貪心選擇。

  • 時間復雜度:Kruskal 算法主要為 O(Elog?E) ;Prim 算法為 O(Elog?V) 。

  • 實例與代碼:通過一個實例和 Python 代碼演示了 MST 的求解過程。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/77535.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/77535.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/77535.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

LeetCode hot 100—編輯距離

題目 給你兩個單詞 word1 和 word2&#xff0c; 請返回將 word1 轉換成 word2 所使用的最少操作數 。 你可以對一個單詞進行如下三種操作&#xff1a; 插入一個字符刪除一個字符替換一個字符 示例 示例 1&#xff1a; 輸入&#xff1a;word1 "horse", word2 &q…

2.3 Spark運行架構與流程

Spark運行架構與流程包括幾個核心概念&#xff1a;Driver負責提交應用并初始化作業&#xff0c;Executor在工作節點上執行任務&#xff0c;作業是一系列計算任務&#xff0c;任務是作業的基本執行單元&#xff0c;階段是一組并行任務。Spark支持多種運行模式&#xff0c;包括單…

NO.82十六屆藍橋杯備戰|動態規劃-從記憶化搜索到動態規劃|下樓梯|數字三角形(C++)

記憶化搜索 在搜索的過程中&#xff0c;如果搜索樹中有很多重復的結點&#xff0c;此時可以通過?個"備忘錄"&#xff0c;記錄第?次搜索到的結果。當下?次搜索到這個結點時&#xff0c;直接在"備忘錄"??找結果。其中&#xff0c;搜索樹中的?個?個結點…

使用 VBA 宏創建一個選擇全部word圖片快捷指令,進行圖片格式編輯

使用 VBA 宏批量選擇圖片 ? 第一步&#xff1a;創建 .dotm 加載項文件 1、使用環境 office word 365&#xff0c;文件格式為.docx 圖片格式為.PNG 2、創建 .dotm 加載項文件 打開 Word&#xff0c;新建一個空白文檔。 按下 Alt F11 打開 VBA 編輯器。 點擊菜單欄&#xff…

深度學習的下一個突破:從圖像識別到情境理解

引言 過去十年&#xff0c;深度學習在圖像識別領域取得了驚人的突破。從2012年ImageNet大賽上的AlexNet&#xff0c;到后來的ResNet、EfficientNet&#xff0c;再到近年來Transformer架構的崛起&#xff0c;AI已經能在許多任務上超越人類&#xff0c;比如人臉識別、目標檢測、醫…

使用dyn4j做碰撞檢測

文章目錄 前言一、環境準備添加依賴基本概念 二、實現步驟1.創建世界2.添加物體3.設置碰撞監聽器4.更新世界 三、完整代碼示例四、優化補充總結 前言 dyn4j 提供了高效的碰撞檢測和物理模擬功能&#xff0c;適用于游戲開發、動畫制作以及其他需要物理交互的場景。通過簡單的 A…

VS Code settings.json 文件中常用的預定義變量?及其用途說明

VS Code settings.json 常用預定義變量 以下是 Visual Studio Code 配置文件中常用的預定義變量列表&#xff1a; 1. 工作區相關變量 變量描述示例值${workspaceFolder}當前工作區根目錄的絕對路徑C:/projects/my-project${workspaceFolderBasename}工作區文件夾名稱&#x…

elasticSearch-搜索引擎

搜索引擎的優勢 有了數據庫分頁查詢&#xff0c;為什么還需要搜索引擎&#xff1f; 搜索引擎速度上很快數據庫分頁查詢&#xff0c;隨著數據庫數據量增大&#xff0c;頁數靠后&#xff0c;會導致搜索速度變慢&#xff0c;但是搜索引擎不會搜索引擎支持分詞查詢&#xff0c;地…

安裝OpenJDK1.8 17 (macos M芯片)

安裝OpenJDK 1.8 下載完后&#xff0c;解壓&#xff0c;打開 環境變量的配置文件即可 vim ~/.zshrc #export JAVA_HOME/Users/xxxxx/jdk-21.jdk/Contents/Home #export JAVA_HOME/Users/xxxxx/jdk-17.jdk/Contents/Home #export JAVA_HOME/Users/xxxxx/jdk-11.jdk/Contents…

斷言與反射——以golang為例

斷言 x.(T) 檢查x的動態類型是否是T&#xff0c;其中x必須是接口值。 簡單使用 func main() {var x interface{}x 100value1, ok : x.(int)if ok {fmt.Println(value1)}value2, ok : x.(string)if ok {//未打印fmt.Println(value2)} }需要注意如果不接受第二個參數就是OK,這…

Java設計模式:系統性解析與核心模式

一、設計模式三大分類總覽 創建型模式&#xff08;5種&#xff09; 核心目標&#xff1a;對象創建的優化與解耦 單例模式&#xff08;Singleton&#xff09; 工廠模式&#xff08;Factory&#xff09; 抽象工廠模式&#xff08;Abstract Factory&#xff09; 建造者模式&#…

Elasticsearch 向量數據庫,原生支持 Google Cloud Vertex AI 平臺

作者&#xff1a;來自 Elastic Valerio Arvizzigno Elasticsearch 將作為第一個第三方原生語義對齊引擎&#xff0c;支持 Google Cloud 的 Vertex AI 平臺和 Google 的 Gemini 模型。這使得聯合用戶能夠基于企業數據構建完全可定制的生成式 AI 體驗&#xff0c;并借助 Elastics…

408 計算機網絡 知識點記憶(7)

前言 本文基于王道考研課程與湖科大計算機網絡課程教學內容&#xff0c;系統梳理核心知識記憶點和框架&#xff0c;既為個人復習沉淀思考&#xff0c;亦希望能與同行者互助共進。&#xff08;PS&#xff1a;后續將持續迭代優化細節&#xff09; 往期內容 408 計算機網絡 知識…

10-MySQL-性能優化思路

1、優化思路 當我們發現了一個慢SQL的問題的時候,需要做性能優化,一般我們是為了提高SQL查詢更快,一個查詢的流程由下圖的各環節組成,每個環節都會消耗時間,要減少消耗時候需要從各個環節都分析一遍。 2 連接配置優化 第一個環節是客戶端連接到服務端,這塊可能會出現服務…

Docker:安裝與部署 Nacos 的技術指南

1、簡述 Nacos(Dynamic Naming and Configuration Service)是阿里巴巴開源的一個動態服務發現、配置管理和服務治理的綜合解決方案,適用于微服務架構。 Nacos 主要功能: 服務發現與注冊:支持 Dubbo、Spring Cloud 等主流微服務框架的服務發現與注冊。動態配置管理:支持…

【非機動車檢測】用YOLOv8實現非機動車及駕駛人佩戴安全帽檢測

非機動車及駕駛人佩戴安全帽檢測任務的意義主要包括以下幾點&#xff1a; 保障行車安全&#xff1a;非機動車包括自行車、電動車等&#xff0c;佩戴安全帽能夠有效保護騎車人頭部&#xff0c;減少因交通事故造成的頭部傷害風險&#xff0c;提高行車安全系數。 符合交通法規&am…

壹起航:15年深耕互聯網營銷,助力中國工廠出海獲客

在全球化浪潮下&#xff0c;越來越多的中國工廠渴望拓展海外市場&#xff0c;但面臨品牌建立、穩定詢盤獲取及營銷成本降低等多重挑戰。壹起航憑借15年的豐富經驗&#xff0c;整合外貿建站、SEO優化及海外短視頻營銷&#xff0c;為中國工廠提供一站式出海解決方案。 一、外貿獨…

Emacs 折騰日記(二十)——修改emacs的一些默認行為

上一篇我們完成了emacs輸入法的配置以及將emacs配置成了使用vim的操作方式。但是emacs目前有些默認行為我不太喜歡&#xff0c;這節我們一起來修改它 備份設置 我們打開emacs的配置文件所在路徑&#xff0c;發現有大量的~結尾的文件&#xff0c;這是emacs的備份文件。這里&am…

聊透多線程編程-線程基礎-4.C# Thread 子線程執行完成后通知主線程執行特定動作

在多線程編程中&#xff0c;線程之間的同步和通信是一個常見的需求。例如&#xff0c;我們可能需要一個子線程完成某些任務后通知主線程&#xff0c;并由主線程執行特定的動作。本文將基于一個示例程序&#xff0c;詳細講解如何使用 AutoResetEvent 來實現這種場景。 示例代碼…

【網絡安全 | 項目開發】Web 安全響應頭掃描器(提升網站安全性)

原創項目,未經許可,不得轉載。 文章目錄 項目簡介工作流程示例輸出技術棧項目代碼使用說明項目簡介 安全響應頭是防止常見 Web 攻擊(如點擊劫持、跨站腳本攻擊等)的有效防線,因此合理的配置這些頭部信息對任何網站的安全至關重要。 Web 安全響應頭掃描器(Security Head…