圖的最小生成樹算法: Prim算法和Kruskal算法(C++)

上一節我們學習了最短路徑算法, 這一節來學習最小生成樹.

最小生成樹(Minimum Spanning Tree, MST)算法是圖論中的一種重要算法, 主要用于在加權無向圖中找到一棵生成樹, 使得這棵樹包含圖中的所有頂點, 并且所有邊的權重之和最小. 這樣的樹被稱為最小生成樹. 最小生成樹廣泛應用于網絡設計, 電路布線等領域. 主要有兩種算法 Prim 算法和 Kruskal 算法.


環境要求

本文所用樣例在Windows 11以及Ubuntu 24.04上面編譯通過.

  1. Windows: 使用[Visual Studio],
  2. Ubuntu: 使用 Clang 18.1.3. (Ubuntu 24.04 系統安裝版本)
  3. GCC 無法編譯直接本項目代碼, 因為本文代碼使用了 C++20 Module, 而 GCC 對此支持不完整.

關于 Module 的更多信息, 請參考我之前的博客: CMake 構建 C++20 Module 實例(使用 MSVC)

本項目工程目錄: 圖論代碼


Prim 算法

Prim 算法是一種用于尋找加權無向圖的最小生成樹(Minimum Spanning Tree, MST)的經典貪心算法. 它由捷克數學家 Vojtěch Jarník 在 1930 年提出, 后來又被計算機科學家 Robert C. Prim 獨立發現, 并因此得名. Prim 算法特別適用于稠密圖, 即邊的數量接近頂點數平方的情況.

算法步驟

Prim 算法的基本思想是從一個任意選擇的起始頂點開始構建最小生成樹, 逐步將距離當前生成樹最近的頂點加入到生成樹中, 直到所有頂點都被包含為止. 具體步驟如下:

  1. 初始化:

    • 選擇任意一個頂點作為起始點, 將其標記為已訪問.
    • 初始化一個優先隊列(或最小堆), 用來存儲尚未訪問的頂點及其與當前生成樹的最短距離. 初始時, 除了起始頂點外, 其他所有頂點的距離設為無窮大(表示還未連接).
  2. 迭代過程:

    • 從優先隊列中取出距離當前生成樹最近的頂點 u u u, 并將其標記為已訪問.
    • 對于頂點 u u u 的所有鄰接頂點 v v v, 如果 v v v 尚未被訪問, 并且通過 u u u 到達 v v v 的距離比之前記錄的距離更短, 則更新 v v v 的距離值, 并將( v v v, 距離)對插入或更新到優先隊列中.
  3. 終止條件:

    • 當優先隊列為空, 或者所有頂點都已被訪問時, 算法結束. 此時, 已經找到了最小生成樹.
偽代碼
// 輸入: 一個加權無向圖G = (V, E), 其中V是頂點集合, E是邊集合
// 輸出: 最小生成樹MST的邊集Prim(G, start_vertex):// 初始化MST = []  // 存儲最小生成樹的邊priority_queue = new MinHeap()  // 優先隊列(最小堆), 存儲(權重, 頂點)對visited = new Set()  // 已訪問頂點集合add start_vertex to visited// 將起始頂點的所有鄰接邊加入優先隊列for each neighbor in G.adjacent(start_vertex):if neighbor not in visited:priority_queue.insert((neighbor, weight(start_vertex, neighbor), start_vertex))// 主循環while not priority_queue.isEmpty():// 取出優先隊列中權重最小的邊(u, v)(u, weight_uv, previous_u) = priority_queue.extractMin()if u in visited:continue  // 如果頂點u已經被訪問過, 則跳過// 將頂點u標記為已訪問, 并將邊(previous_u, u)加入MSTadd u to visitedadd (previous_u, u, weight_uv) to MST// 對于頂點u的所有鄰接頂點vfor each (v, weight_u_v) in G.adjacent(u):if v not in visited:// 將(v, 權重)對插入或更新到優先隊列中priority_queue.insertOrDecreaseKey((v, weight_u_v, u))return MST

樣例

考慮下面這個圖, 求它的最小生成樹.

sample

  1. 初始化: 假設我們從G開始訪問, 此時標記G為已訪問, 并將與G相鄰的點加入到優先隊列中. 設置其他點的距離為無窮大.
    prim init

  2. 迭代過程:

  • 從優先隊列中取出(G, C), 將C標記為已訪問, 將G-C這條邊加入到結果集中. 訪問C的鄰接點[A, B, D], 更新他們的距離, 由于新的距離更小, 所以將[A, B, D]加入優先隊列中.
    prim c

  • 從優先隊列中取出(C, A). 將A標記為已訪問, 將C-A這條邊加入到結果集中. 訪問A的鄰接點[B, C, D, H], 其中C已經訪問過, 跳過. 將其他的邊加入優先隊列中.

    prim a

  • 從優先隊列中取出(A, B). 將B標記為已訪問, 將A-B這條邊加入到結果集中. 訪問B的鄰接點[A, C, D, E], A, C均已訪問, 跳過; 將其他的邊加入優先隊列中.
    prim b

  • 從優先隊列中取出(B, E). 將E標記為已訪問, 將B-E這條邊加入到結果集中. 訪問E的鄰接點[B, D, F, H], B以訪問,跳過. 將其他的邊加入優先隊列中.
    prim 3

  • 從優先隊列中取出(B, D). 將D標記為已訪問, 將B-D這條邊加入到結果集中. 訪問D的鄰接點[A, B, C, E, F], 其中[A, B, C, E]已訪問, 跳過. 將D,F加入優先隊列.
    prim d

  • 跳過(C, B), (A,D) , (C,D)

  • 從優先隊列中取出(D, F). 將F標記為已訪問, 將D-F這條邊加入到結果集中. 訪問F的鄰接點[D, E], 均已訪問過, 跳過.
    prim f

  • 從優先隊列中取出(G, H). 將H標記為已訪問, 將G-H這條邊加入到結果集中. 訪問H的鄰接點[A, E, G], 均已訪問, 跳過.

    prim h

  • 其他邊的頂點都已經訪問過, 均被跳過, 算法結束. 得到的最小生成樹如下:

ans

實現細節

typedef std::pair<unsigned, int> EdgeWithWeight;
class Prim {public:

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

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

相關文章

矩陣系統源碼搭建的數據管理開發功能解析,支持OEM

一、引言 在矩陣系統中&#xff0c;數據猶如血液&#xff0c;貫穿整個系統的運行。高效的數據管理開發功能是確保矩陣系統穩定、可靠運行的關鍵&#xff0c;它涵蓋了數據的存儲、處理、安全等多個方面。本文將深入探討矩陣系統源碼搭建過程中數據管理功能的開發要點。 二、數據…

DeepSeek 助力 Vue 開發:打造絲滑的日期選擇器(Date Picker),未使用第三方插件

前言&#xff1a;哈嘍&#xff0c;大家好&#xff0c;今天給大家分享一篇文章&#xff01;并提供具體代碼幫助大家深入理解&#xff0c;徹底掌握&#xff01;創作不易&#xff0c;如果能幫助到大家或者給大家一些靈感和啟發&#xff0c;歡迎收藏關注哦 &#x1f495; 目錄 Deep…

操作系統知識點2

1.P&#xff0c;V操作可以實現進程同步&#xff0c;進程互斥&#xff0c;進程的前驅關系 2.先來先服務調度算法是不可搶占的算法 3.UNIX操作系統中&#xff0c;對文件系統中空閑區的管理通常采用成組鏈接法 4.對于FAT32文件系統&#xff0c;它采用的是鏈接結構 5.不同的I/O…

【個人開發】deepspeed+Llama-factory 本地數據多卡Lora微調【完整教程】

文章目錄 1.背景2.微調方式2.1 關鍵環境版本信息2.2 步驟2.2.1 下載llama-factory2.2.2 準備數據集2.2.3 微調模式2.2.3.1 zero-1微調2.2.3.2 zero-2微調2.2.3.3 zero-3微調2.2.3.4 單卡Lora微調 2.2.4 實驗2.2.4.1 實驗1&#xff1a;多GPU微調-zero12.2.4.2 實驗2&#xff1a;…

iOS 中使用 FFmpeg 進行音視頻處理

在 iOS 中使用 FFmpeg 進行音視頻處理,通常需要將 FFmpeg 的功能集成到項目中。由于 FFmpeg 是一個 C 庫,直接在 iOS 中使用需要進行一些配置和封裝。 1. 在 iOS 項目中集成 FFmpeg 方法 1:使用 FFmpeg 預編譯庫 下載 FFmpeg iOS 預編譯庫: 可以從以下項目中獲取預編譯的 …

Elasticsearch:將 Ollama 與推理 API 結合使用

作者&#xff1a;來自 Elastic Jeffrey Rengifo Ollama API 與 OpenAI API 兼容&#xff0c;因此將 Ollama 與 Elasticsearch 集成非常容易。 在本文中&#xff0c;我們將學習如何使用 Ollama 將本地模型連接到 Elasticsearch 推理模型&#xff0c;然后使用 Playground 向文檔提…

openGauss 3.0 數據庫在線實訓課程18:學習視圖管理

前提 我正在參加21天養成好習慣| 第二屆openGauss每日一練活動 課程詳見&#xff1a;openGauss 3.0.0數據庫在線實訓課程 學習目標 掌握openGauss視圖的管理&#xff1a;創建視圖、刪除視圖、查詢視圖的信息、修改視圖的信息。 課程作業 1.創建表&#xff0c;創建普通視圖…

騰訊云大模型知識引擎×DeepSeek賦能文旅

騰訊云大模型知識引擎DeepSeek賦能文旅 ——以合肥文旅為例的技術革新與實踐路徑 一、技術底座&#xff1a;知識引擎與DeepSeek的融合邏輯 騰訊云大模型知識引擎與DeepSeek模型的結合&#xff0c;本質上是**“知識庫檢索增強生成&#xff08;RAG&#xff09;實時聯網能力”**…

利用SkinMagic美化MFC應用界面

MFC(Microsoft Foundation Class)應用程序的界面設計風格通常比較保守,而且雖然MFC框架的控件功能強大且易于集成,但視覺效果較為樸素,缺乏現代感。尤其是MFC應用程序的設計往往以功能實現為核心,界面設計可能顯得較為簡潔甚至略顯呆板,用戶體驗可能不如現代應用程序流暢…

qt QOpenGLTexture詳解

1. 概述 QOpenGLTexture 是 Qt5 提供的一個類&#xff0c;用于表示和管理 OpenGL 紋理。它封裝了 OpenGL 紋理的創建、分配存儲、綁定和設置像素數據等操作&#xff0c;簡化了 OpenGL 紋理的使用。 2. 重要函數 構造函數&#xff1a; QOpenGLTexture(const QImage &image,…

nlp|微調大語言模型初探索(2),訓練自己的聊天機器人

前言 上篇文章記錄了具體的微調語言大模型步驟&#xff0c;以及在微調過程中可能遇見的各種報錯&#xff0c;美中不足的是只是基于開源數據集的微調&#xff0c;今天來記錄一下怎么基于自己的數據集去微調大語言模型&#xff0c;訓練自己的智能機器人&#xff01;&#xff01;&…

Java 大視界 -- 量子計算時代 Java 大數據的潛在變革與應對策略(88)

&#x1f496;親愛的朋友們&#xff0c;熱烈歡迎來到 青云交的博客&#xff01;能與諸位在此相逢&#xff0c;我倍感榮幸。在這飛速更迭的時代&#xff0c;我們都渴望一方心靈凈土&#xff0c;而 我的博客 正是這樣溫暖的所在。這里為你呈上趣味與實用兼具的知識&#xff0c;也…

手機功耗BugReport字段含義介紹

BugReport一般用來分析功耗問題&#xff0c;例如休眠待機&#xff0c;后臺待機&#xff0c;游戲&#xff0c;視頻&#xff0c;相機場景等 BugReport字段含義介紹 BugReport字段 含義 備注 Reboot 設備的重啟事件 CPU running CPU運行狀態&#xff0c;休眠 或者 喚醒 只有…

什么是 近端策略優化算法PPO

什么是 近端策略優化算法PPO 近端策略優化算法(Proximal Policy Optimization,PPO)是OpenAI公司于2017年開發的一系列無模型強化學習算法,用于優化策略網絡以最大化累計獎勵。以下是具體介紹及示例: 算法原理 策略梯度:PPO基于策略梯度算法,通過估計策略網絡的梯度來更…

計算機視覺-局部特征

一、局部特征 1.1全景拼接 先用RANSAC估計出變換&#xff0c;就可以拼接兩張圖片 ①提取特征 ②匹配特征 ③拼接圖像 1.2 點的特征 怎么找到對應點&#xff1f;&#xff08;才能做點對應關系RANSAC&#xff09; &#xff1a;特征檢測 我們希望找到的點具有的特征有什么特…

個人搭建CDN加速服務 特網科技

在互聯網快速發展的今天&#xff0c;網站的加載速度對用戶體驗有著至關重要的影響&#xff0c;傳統的網頁加載方式依賴于服務器的性能和網絡環境&#xff0c;這使得某些網站的頁面加載時間過長&#xff0c;用戶體驗不佳&#xff0c;為了解決這個問題&#xff0c;許多企業開始采…

類型通配符上限

主函數 package typeWildcardTop;import java.util.ArrayList;public class typeWildcardTopTest {/**/public static void main(String[] args) { // test1();test2();}/*測試showList接收ArrayList類型 ArrayList接收各種類型參數創建animals cats mincats集合 傳入s…

OpenCV(1):簡介、安裝、入門案例、基礎模塊

1 OpenCV 簡介 OpenCV 是一個功能強大、應用廣泛的計算機視覺庫&#xff0c;它為開發人員提供了豐富的工具和算法&#xff0c;可以幫助他們快速構建各種視覺應用。隨著計算機視覺技術的不斷發展&#xff0c;OpenCV 也將會繼續發揮重要的作用。OpenCV 提供了大量的計算機視覺算法…

FTP自動上傳/vue打包自動上傳

ftp自動上傳 在我們平時開發項目時&#xff0c;需要將本地代碼編譯后上傳到服務器&#xff0c;我們可以借助Node.js庫中的ssh2來實現自動上傳 首先我們先來說下ssh2的安裝和使用 安裝ssh2 npm install ssh2創建ssh2實例 const { Client } require(ssh2);連接服務器 const c…

SQL復習

SQL復習 MySQL SQL介紹 SQL SQL的全拼是什么&#xff1f; SQL全拼&#xff1a;Structured Query Language&#xff0c;也叫結構化查詢語言。 SQL92和SQL99有什么區別呢&#xff1f; SQL92和SQL99分別代表了92年和99年頒布的SQL標準。 在 SQL92 中采用&#xff08;&#xff…