mst[講課留檔]

最小生成樹(Minimum Spanning Tree)

(1)概念

我們知道,是有 n n n個結點, n ? 1 n-1 n?1條邊的無向無環的連通圖。

一個連通圖的生成樹是一個極小的連通子圖,它包含圖中全部的 n n n個頂點,但只有構成一棵樹的 n ? 1 n-1 n?1條邊。

最小生成樹就是一個帶權圖,每個邊都有一個邊權,一顆生成樹的權值是該樹邊所有邊權的和, M S T MST MST就是所有生成樹中最小的一個。

(2)Prim算法(遍歷點的算法)

普里姆算法在找最小生成樹時,將頂點分為兩類,一類是在查找的過程中已經包含在生成樹中的頂點(假設為 A 類),剩下的為不在生成樹中的(假設為 B 類)。

對于給定的連通網,起始狀態全部頂點都歸為 B 類。在找最小生成樹時,選定任意一個頂點作為起始點,并將之從 B 類移至 A 類;然后找出 B 類中到 A 類中的頂點之間權值最小的頂點,將之從 B 類移至 A 類,如此重復,直到 B 類中沒有頂點為止。所走過的頂點和邊就是該連通圖的最小生成樹。

請添加圖片描述

int dis[N];
int mp[N][N];
bool vis[N];void work() {int n, m;cin >> n >> m;int ans = 0;memset(vis, 0, sizeof vis);memset(mp, 0x3f3f3f3f, sizeof mp);for (int i = 0; i < n; ++i) {int u, v, w;cin >> u >> v >> w;mp[u][v] = w;mp[v][u] = w;}for (int i = 0; i < n; ++i) {dis[i] = 0x3f3f3f3f;}dis[0] = 0;vis[0] = 1;for (int i = 1; i < n; ++i) {dis[i] = min(dis[i], mp[0][i]);}for (int i = 1; i < n; ++i) {//這里的外層循環是循環遍數,與i值無關double minn = 0x3f3f3f3f;int pos = -1;for (int j = 1; j < n; ++j) {//每次循環找出與已排聯通塊距離最近的點if (!vis[j] && minn > dis[j]) {pos = j;minn = dis[j];}}ans += minn;vis[pos] = 1;for (int j = 0; j < n; ++j) {//刷新未連接點的距離最小值dis[j] = min(dis[j], mp[pos][j]);}}cout << ans << '\n';
}

正確性顯然。

復雜度是 O ( n 2 ) O(n^2) O(n2)級別的,但是我們可以使用堆優化降到 O ( n l o g n ) O(nlogn) O(nlogn),之后講最短路的時候會講堆優化。

(3)Kruskal算法(遍歷邊的算法)

克魯斯卡爾算法(Kruskal)是一種使用貪婪方法的最小生成樹算法。 該算法初始將圖視為森林,圖中的每一個頂點視為一棵單獨的樹。 一棵樹只與它的鄰接頂點中權值最小且不違反最小生成樹屬性(不構成環)的樹之間建立連邊。

請添加圖片描述

利用并查集可以快速實現查找兩個點是否已經連接

int n, m;
int f[105];
struct road {int a, b, v;
} arr[305];int find(int a) {if (f[a] == a)return a;elsereturn f[a] = find(f[a]);
}void join(int a, int b) {if (find(a) != find(b))f[find(a)] = find(b);
}bool cmp(road a, road b) {return a.v < b.v;
}void work() {cin >> n >> m;int a, b, c;for (int i = 1; i <= n; ++i) {f[i] = i;}int ans = 0;for (int i = 0; i < m; ++i) {cin >> arr[i].a >> arr[i].b >> arr[i].v;}sort(arr, arr + m, cmp);//先按路的權值排序,如果兩點的祖先不是一個就加上然后合并。for (int i = 0; i < m; ++i) {if (find(arr[i].a) != find(arr[i].b)) {ans += arr[i].v;join(arr[i].a, arr[i].b);}}cout << ans << '\n';return 0;
}

正確性證明:

給一帶權連通的樹一定會有至少一棵生成樹,那么這些生成樹中間必然會會存在至少一棵最小生成樹。

假設 T T T是用 k r u s k a l kruskal kruskal求出來的最小生成樹,而 U U U是這個圖的最小生成樹,要證 U = T U = T U=T
然而如果 T ≠ U T \neq U T=U,那么至少存在一條邊在 T T T中,不在 U U U中,假設存在 k k k條邊存在 T T T中不存在 U U U中。
接下來進行 k k k次變換:
每次將在 T T T中不在 U U U中的最小的邊 f f f拿出來放到 U U U中,那么 U U U中必然形成一條唯一的環路,我們取出這個環路上最小的且不在 T T T中的邊 e e e放回到 T T T中,這樣的邊 e e e一定是存在的,因為之前的 T T T不存在環路(如果 e e e T T T中那么就可能和 f f f形成環路)。

在這里插入圖片描述
現在證明 f f f e e e權值的關系:

假設 f < e f < e f<e,那么后來形成的 U U U是權值之和更小了,與 U U U是最小生成樹矛盾。 實際上,不可能在 U U U中拿到大于 f f f的邊,因為把 f f f拿走后,如果小于 f f f的邊都不成立,至少 f f f是一個符合條件的邊會被那回。

假設 f > e f > e f>e,那么根據 k r u s k a l kruskal kruskal的做法, e e e是在 f f f之前被取出來的邊但是被舍棄了,一定是因為 e e e和比 e e e小的邊形成了環路,而比 e e e小的邊都是存在 U U U中的,而 e e e和這些邊并沒有形成環路,于假設矛盾。

于是 f f f一定和 e e e相等的, k k k次變換后, T T T U U U的權值之和是相等的。

最小生成樹的值也是相等的。

復雜度是 O ( n l o g n ) O(nlogn) O(nlogn)級別的,一般有mst就用這個。

int f[N];
struct road {int a, b, v;
} arr[N];
int tot = 0;int find(int a) {if (f[a] == a)  return a;return f[a] = find(f[a]);
}void join(int a, int b) {if (find(a) != find(b)) f[find(a)] = find(b);
}bool cmp(road a, road b) {return a.v < b.v;
}void work() {int a, b;cin >> a >> b;for (int i = 1; i <= b; ++i) {f[i] = i;arr[i] = {0, i, a};}tot = b;for (int i = 1; i <= b; ++i) {for (int j = 1; j <= b; ++j) {int x; cin >> x;if (x == 0) continue;else arr[++tot] = {i, j, x};}}ll ans = 0;sort(arr + 1, arr + 1 + tot, cmp);for (int i = 1; i <= tot; ++i) {if (find(arr[i].a) != find(arr[i].b)) {ans += arr[i].v;join(arr[i].a, arr[i].b);b--;}if (b == 0) break;}cout << ans << '\n';
}

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

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

相關文章

內容營銷專家劉鑫煒:越是賺不到錢,越要加大推廣力度

這兩天&#xff0c;一位跟我們有長期合作關系的小微企業主老蘇問我。 “現在錢這么不好賺&#xff0c;品牌推廣應該怎么做&#xff1f;” 我說&#xff1a;“這是好機會&#xff0c;加大投放力度&#xff01;” 老蘇很是不解&#xff0c;這時候不開源節流&#xff0c;還要加…

使用Git從Github上克隆倉庫,修改并提交修改

前言 本次任務主要是進行github提交修改的操作練習實踐&#xff0c;本文章是對實踐過程以及遇到的問題進行的一個記錄。 在此之前&#xff0c;我已經簡單使用過github&#xff0c;Git之前已經下好了&#xff0c;所以就省略一些步驟。 步驟記錄 注冊github賬號&#xff0c;gi…

【C++】C++指針在線程中調用與受保護內存空間讀取方法

引言 在C的多線程編程中&#xff0c;正確地管理內存和同步訪問是確保程序穩定性和安全性的關鍵。特別是當涉及到指針在線程中的調用時&#xff0c;對受保護內存空間的訪問必須謹慎處理&#xff0c;以防止數據競爭、死鎖和內存損壞等問題。本文將詳細探討C指針在線程中調用時如何…

理解 React 的嚴格模式

文章目錄 有什么優劣優點&#xff1a;缺點&#xff1a; 使用場景如何使用為整個應用啟用嚴格模式一部分代碼啟用嚴格模式 React 的 Strict Mode&#xff08;嚴格模式&#xff09;是一種用于檢測應用中潛在問題的開發工具。它不會渲染任何可見的 UI 元素&#xff0c;而是通過激活…

element-ui如何做表單驗證

Element UI 使用表單驗證通常涉及兩個主要組件&#xff1a;el-form 和 el-form-item。 el-form 負責管理表單數據和驗證規則&#xff0c;而 el-form-item 用于定義需要驗證的表單項。 <template><el-form :model"form" :rules"rules" ref"fo…

易校網校園綜合跑腿小程序源碼修復運營版

簡介&#xff1a; 易校網校園綜合跑腿小程序源碼修復運營版&#xff0c;帶服務端客戶端前端文檔說明。 源碼安裝方法&#xff1a; 需要準備小程序服務號 服務器 備案域名 校園網跑腿小程序源碼需要準備 1.小程序 2.服務器&#xff08;推薦配置2h4g3m&#xff09; 3.域名…

使用JMeter+Grafana+Influxdb搭建可視化性能測試監控平臺

【背景說明】 使用jmeter進行性能測試時&#xff0c;工具自帶的查看結果方式往往不夠直觀和明了&#xff0c;所以我們需要搭建一個可視化監控平臺來完成結果監控&#xff0c;這里我們采用三種JMeterGrafanaInfluxdb的方法來完成平臺搭建 【實現原理】 通過influxdb數據庫存儲…

開源模型應用落地-FastAPI-助力模型交互-WebSocket篇(五)

一、前言 使用 FastAPI 可以幫助我們更簡單高效地部署 AI 交互業務。FastAPI 提供了快速構建 API 的能力,開發者可以輕松地定義模型需要的輸入和輸出格式,并編寫好相應的業務邏輯。 FastAPI 的異步高性能架構,可以有效支持大量并發的預測請求,為用戶提供流暢的交互體驗。此外,F…

【圖論】樹鏈剖分

樹鏈剖分詳解 - 自為風月馬前卒 - 博客園 (cnblogs.com) P3384 【模板】重鏈剖分/樹鏈剖分 - 洛谷 | 計算機科學教育新生態 (luogu.com.cn) #include<iostream> using namespace std;void dfs1(int u,int father){ fa[u]father; dep[u]dep[father]1; sz[u]1;for(int ih…

SpringBoot中整合ONLYOFFICE在線編輯

SpringBoot整合OnlyOffice SpringBoot整合OnlyOffice實現在線編輯1. 搭建私有的OnlyOffice的服務2. SpringBoot進行交互2.1 環境2.2 我們的流程2.3 接口規劃2.3.1 獲取編輯器配置的接口2.3.2 文件下載地址2.3.3 文件下載地址 3. 總結4. 注意4.1 你的項目的地址一定一定要和only…

Java中的單元測試與集成測試最佳實踐

Java中的單元測試與集成測試最佳實踐 大家好&#xff0c;我是免費搭建查券返利機器人省錢賺傭金就用微賺淘客系統3.0的小編&#xff0c;也是冬天不穿秋褲&#xff0c;天冷也要風度的程序猿&#xff01;今天我們將深入探討Java中的單元測試與集成測試最佳實踐。在軟件開發中&am…

三層交換基礎

一、什么是三層交換 三層交換是一種在OSI模型第三層&#xff0c;即網絡層上工作的網絡設備技術&#xff0c;它整合了二層交換機的功能和路由器的部分功能&#xff0c;以實現更高效的網絡數據轉發和路由選擇。三層交換技術的核心在于結合了二層交換技術和三層轉發技術&#xff…

【RabbitMQ實戰】Springboot 整合RabbitMQ組件,多種編碼示例,帶你實踐 看完這一篇就夠了

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 前言一、對RabbitMQ管理界面深入了解1、在這個界面里面我們可以做些什么&#xff1f; 二、編碼練習&#xff08;1&#xff09;使用direct exchange(直連型交換機)&a…

2024 年的 13 個 AI 趨勢

2024 年的 13 個 AI 趨勢 人工智能對環境的影響和平人工智能人工智能支持的問題解決和決策針對人工智能公司的訴訟2024 年美國總統大選與人工智能威脅人工智能、網絡犯罪和社會工程威脅人工智能治療孤獨與對人工智能的情感依賴人工智能影響者中國爭奪人工智能霸主地位人工智能…

Java中的機器學習模型集成與訓練

Java中的機器學習模型集成與訓練 大家好&#xff0c;我是免費搭建查券返利機器人省錢賺傭金就用微賺淘客系統3.0的小編&#xff0c;也是冬天不穿秋褲&#xff0c;天冷也要風度的程序猿&#xff01;今天我們將探討在Java中如何進行機器學習模型的集成與訓練。隨著人工智能和機器…

【Lua小知識】Vscode中Emmylua插件大量報錯的解決方法

起因 Vscode寫Lua用的好好的&#xff0c;最近突然出現了大量報錯。 看報錯是有未定義的全局變量&#xff0c;這里查日志才發現是由于0.7.5版本新增診斷啟用配置&#xff0c;所以導致了原先好的代碼&#xff0c;現在出現了大量的報錯。 解決方案一 最直接的方法當然是在配置中直…

用攝像頭實現識別道路中的車道線、行人與車輛檢測(級聯分類器、HOG+SVM、行人檢測)

基于樹莓派的智能小車&#xff0c;用攝像頭實現識別道路中的車道線識別、行人檢測與車輛檢測。 本項目旨在開發一套基于攝像頭的智能道路環境感知系統&#xff0c;該系統能夠實時識別道路中的車道線、行人與車輛&#xff0c;為自動駕駛汽車、智能交通管理以及輔助駕駛系統提供關…

LeetCode熱題100刷題3:3. 無重復字符的最長子串、438. 找到字符串中所有字母異位詞、560. 和為 K 的子數組

3. 無重復字符的最長子串 滑動窗口、雙指針 class Solution { public:int lengthOfLongestSubstring(string s) {//滑動窗口試一下//英文字母、數字、符號、空格,ascii 一共包含128個字符vector<int> pos(128,-1);int ans 0;for(int i0,j0 ; i<s.size();i) {//s[i]…

python 中的生成器

目錄 生成器示例基本生成器示例無限序列生成器使用生成器表達式實用示例&#xff1a;按行讀取大文件生成器的 send、throw 和 close 方法 生成器和迭代器迭代器&#xff08;Iterator&#xff09;定義創建使用示例 生成器&#xff08;Generator&#xff09;定義創建使用示例 主要…

【python學習】自定義函數的一些高級用法-2

8. 生成器函數 生成器函數允許你定義一個可以“記住”其當前執行狀態的函數&#xff0c;并在下次調用時從上次離開的位置繼續執行。生成器函數使用yield關鍵字而不是return。 def simple_generator(): yield 1 yield 2 yield 3 gen simple_generator() print(next(gen)) # …