代碼隨想錄算法訓練營 Day58 圖論Ⅷ 拓撲排序 Dijkstra

圖論

題目

117. 軟件構建
拓撲排序:給出一個有向圖,把這個有向圖轉成線性的排序就叫拓撲排序
當然拓撲排序也要檢測這個有向圖是否有環,即存在循環依賴的情況,因為這種情況是不能做線性排序的。所以拓撲排序也是圖論中判斷有向無環圖的常用方法
本題使用 BFS 的拓撲排序思路
在這里插入圖片描述

尋找出發邊,特征是入度為0 出度為2,也就是沒有邊指向它,而它有兩條邊是指出去的。
接下來我給出拓撲排序的過程,其實就兩步
1. 找到入度為0 的節點,加入結果集
2. 將該節點從圖中移除
循環以上兩步,直到所有節點都在圖中被移除了。
模擬過程

在這里插入圖片描述
在這里插入圖片描述

在這里插入圖片描述
如果有環出現
在這里插入圖片描述
這個圖,我們只能將入度為0 的節點0 接入結果集。
之后,節點1、2、3、4 形成了環,找不到入度為0 的節點了,所以此時結果集里只有一個元素。
那么如果我們發現結果集元素個數不等于圖中節點個數,我們就可以認定圖中一定有有向環!
這也是拓撲排序判斷有向環的方法。

#include <iostream>
#include <vector>
#include <queue>
#include <unordered_map>using namespace std;int main() {int m, n, s, t;cin >> n >> m;// 記錄入度vector<int> inDegree(n, 0);// 使用鄰接表記錄圖依賴關系unordered_map<int, vector<int>> umap;// 記錄結果vector<int> res;for (int i = 0; i < m; ++i) {cin >> s >> t;inDegree[t]++;umap[s].push_back(t);}// 拓撲排序開始queue<int> que;// 尋找入度為0的元素加入隊列for (int i = 0; i < n; ++i) {if (inDegree[i] == 0) que.push(i);}while (!que.empty()) {// 當前節點int cur = que.front();que.pop();res.push_back(cur);// 遍歷節點指向for (int idx : umap[cur]) {inDegree[idx]--; // 通過 入度-- 實現圖中刪除這個節點if (inDegree[idx] == 0) que.push(idx);}}// 若不等于n說明有向圖中有環if (res.size() == n) {for (int i = 0; i < n-1; ++i) {cout << res[i] << " ";}cout << res[n-1] << endl;}else cout << -1 << endl;
}

47. 參加科學大會(第六期模擬筆試)
最短路徑 dijkstra 算法,求圖中最短路徑
在這里插入圖片描述

思路
類似于 prim 算法,dijkstra 算法 同樣是貪心的思路,不斷尋找距離 源點最近的沒有訪問過的節點。
這里我也給出 dijkstra三部曲
1. 第一步,選源點到哪個節點近且該節點未被訪問過
2. 第二步,該最近節點被標記訪問過
3. 第三步,更新非訪問節點到源點的距離(即更新minDist數組)
在dijkstra算法中,同樣有一個數組很重要,起名為:minDist。
minDist數組用來記錄每一個節點距離源點的最小距離
理解這一點很重要,也是理解 dijkstra 算法的核心所在。
樸素算法
初始化節點這里在強點一下 minDist數組的含義:記錄所有節點到源點的最短路徑,那么初始化的時候就應該初始為最大值,這樣才能在后續出現最短路徑的時候及時更新。
在這里插入圖片描述

(圖中,max 表示默認值,節點0 不做處理,統一從下標1 開始計算,這樣下標和節點數值統一,方便大家理解,避免搞混)
源點(節點1) 到自己的距離為0,所以 minDist[1] = 0
此時所有節點都沒有被訪問過,所以 visited數組都為0
以下為dijkstra 三部曲
1、選源點到哪個節點近且該節點未被訪問過,源點距離源點最近,距離為0,且未被訪問。
2、該最近節點被標記訪問過,標記源點訪問過
3、更新非訪問節點到源點的距離(即更新minDist數組) ,如圖:
在這里插入圖片描述

更新 minDist數組,即:源點(節點1) 到 節點2 和 節點3的距離。
- 源點到節點2的最短距離為1,小于原minDist[2]的數值max,更新minDist[2] = 1
- 源點到節點3的最短距離為4,小于原minDist[3]的數值max,更新minDist[3] = 4
可能有錄友問:為啥和 minDist[2] 比較?
再強調一下 minDist[2] 的含義,它表示源點到節點2的最短距離,那么目前我們得到了源點到節點2的最短距離為1,小于默認值max,所以更新。 minDist[3]的更新同理
在這里插入圖片描述
在這里插入圖片描述

在這里插入圖片描述

#include <iostream>
#include <vector>
#include <climits>using namespace std;// 與 Prim 相似度達到 90%
int main(){// 處理輸入int n, m, p1, p2, val;cin >> n >> m;// 使用鄰接矩陣創建圖vector<vector<int>> grid(n+1, vector<int>(n+1, INT_MAX));for (int i = 0; i < m; ++i) {cin >> p1 >> p2 >> val;grid[p1][p2] = val;}int start = 1;int end = n;// 存儲從原點到每個節點的最短距離vector<int> minDist(n+1, INT_MAX);// 記錄節點訪問情況 prim是isTree標記vector<bool> vis(n+1, false);minDist[start] = 0; // 起始點到自身距離為0// 遍歷所有節點計算最短距離for (int i = 1; i <= n; ++i) {int minVal = INT_MAX;int cur = 1;// prim 1.選擇距離生成樹最近的節點// dijkstra 1.選擇距離原點最近尾訪問過的節點for (int v = 1; v <= n; ++v) {if (!vis[v] && minDist[v] < minVal) {minVal = minDist[v];cur = v;}}// prim 2.最近節點加入生成樹// dijkstra 2.標記訪問vis[cur] = true;// prim 3.更新非生成樹到生成樹的距離// dijkstra 3.更新非訪問節點到原點距離 與Prim的核心不同點for (int v = 1; v <= n; ++v) {// cur為當前最小距離節點值if (!vis[v] && grid[cur][v] != INT_MAX && minDist[cur] + grid[cur][v] < minDist[v]) {minDist[v] = minDist[cur] + grid[cur][v];}}}if (minDist[end] == INT_MAX) cout << -1 << endl;else cout << minDist[end] << endl; // 抵達終點return 0;
}

Prim 算法

#include <iostream>
#include <vector>
#include <climits>using namespace std;int main() {// 構造圖int v, e;cin >> v >> e;int x, y, k;// 構造最大值10001vector<vector<int>> grid(v+1, vector<int>(v+1, 10001));for (int i = 0; i < e; ++i) {cin >> x >> y >> k;grid[x][y] = k;grid[y][x] = k;}// 所有節點到最小生成樹的距離vector<int> minDist(v+1, 10001);// 節點是否在最小生成樹中vector<bool> isTree(v+1, false);// 最小生成樹只需要v-1條邊就可以鏈接n個頂點 序號從1開始for (int i = 1; i < v; ++i) {// prim 三部曲 1 選擇距離生成樹最近的節點int cur = -1;int minVal = INT_MAX;// 遍歷當前頂點 尋找 1.不在生成樹內 2.最近生成樹的節點for (int j = 1; j <= v; ++j) {if (!isTree[j] && minDist[j] < minVal) {minVal = minDist[j];cur = j;}}// prim 三部曲 2 最近節點加入生成樹isTree[cur] = true;// prim 三部曲 3 更新非生成樹到生成樹的距離 即更新 minDist數組for (int j = 1; j <= v; ++j) {// 更新條件 1.不在生成樹中 2.與cur相連的某節點的權值 比 該某節點距離最小生成樹的距離小if (!isTree[j] && grid[cur][j] < minDist[j]) {minDist[j] = grid[cur][j];}}}// 統計總距離int res = 0;for (int i = 2; i <= v; ++i) {res += minDist[i];}cout << res << endl;
}

打印 dijkstra 算法的路徑

#include <iostream>
#include <vector>
#include <climits>using namespace std;int main() {int n, m, x, y, val;cin >> n >> m;vector<vector<int>> grid(n+1, vector<int>(n+1, INT_MAX));vector<int> minDist(n+1, INT_MAX);vector<bool> vis(n+1, false);vector<int> parent(n+1, -1); // 打印路徑使用for (int i = 0; i < m; ++i) {cin >> x >> y >> val;grid[x][y] = val;}int start = 1;int end = n;for (int i = 1; i <= n; ++i) {int cur = 1;int minVal = INT_MAX;// 1for (int v = 1; v <= n; ++v) {if (!vis[v] && minDist[v] < minVal) {minVal = minDist[v];cur = v;}}// 2vis[cur] = true;// 3for (int v = 1; v <= n; ++v) {if (!vis[v] && grid[cur][v] != INT_MAX && grid[cur][v] + minDist[cur] < minDist[v]) {minDist[v] = grid[cur][v] + minDist[cur];parent[v] = cur;}}}// 輸出邊for (int i = 1; i <=n; ++i) {cout << parent[i] << "->" << i << endl;}
}

Dijkstra 不能處理負數情況

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

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

相關文章

vscode中launch.json、tasks.json的作用及實例

文章目錄 launch.json是什么作用多環境調試簡單實例進階使用核心配置項解析調試第三方程序 launch.json是什么 顧名思義&#xff1a;它是在.vscode文件夾下的launch.json&#xff0c;所以是vscode啟動調試的配置文件。總結&#xff1a;通過定義調試參數、環境變量和啟動方式&a…

NeRF PyTorch 源碼解讀 - 體渲染

文章目錄 1. 體渲染公式推導1.1. T ( t ) T(t) T(t) 的推導1.2. C ( r ) C(r) C(r) 的推導 2. 體渲染公式離散化3. 代碼解讀 1. 體渲染公式推導 如下圖所示&#xff0c;渲染圖像上點 P P P 的顏色值 c c c 是累加射線 O P → \overrightarrow{OP} OP 在近平面和遠平面范圍…

標題:2025海外短劇爆發年:APP+H5雙端系統開發,解鎖全球流量與變現新大陸

描述&#xff1a; 2025年出海新風口&#xff01;深度解析海外短劇系統開發核心&#xff08;APPH5雙端&#xff09;&#xff0c;揭秘高效開發策略與商業化路徑&#xff0c;助您搶占萬億美元市場&#xff01; 全球娛樂消費模式正在劇變。2025年&#xff0c;海外短劇市場已從藍海…

React JSX語法介紹(JS XML)(一種JS語法擴展,允許在JS代碼中編寫類似HTML的標記語言)Babel編譯

在線調試網站&#xff1a;https://zh-hans.react.dev/learn 文章目錄 JSX&#xff1a;現代前端開發的聲明式語法概述JSX的本質與工作原理什么是JSXJSX轉換流程 JSX語法特性表達式嵌入&#xff08;JSX允許在大括號內嵌入任何有效的JavaScript表達式&#xff09;屬性傳遞&#xf…

Unity UI系統中RectTransform詳解

一、基礎代碼示例 public GameObject node; var rect node.GetComponent<RectTransform>();Debug.Log($"anchoredPosition----{rect.anchoredPosition}"); Debug.Log($"offsetMin.x--{rect.offsetMin}"); Debug.Log($"offsetMax.x--{rect.of…

【數據庫】并發控制

并發控制 在數據庫系統&#xff0c;經常需要多個用戶同時使用。同一時間并發的事務可達數百個&#xff0c;這就是并發引入的必要性。 常見的并發系統有三種&#xff1a; 串行事務執行&#xff08;X&#xff09;&#xff0c;每個時刻只有一個事務運行&#xff0c;不能充分利用…

我們來學mysql -- “數據備份還原”sh腳本

數據備份&還原 說明執行db_backup_cover.sh腳本 說明 環境準備&#xff1a;來源數據庫(服務器A)&#xff1b;目標數據庫(服務器B)dbInfo.sh腳本記錄基本信息 來源庫、目標庫的ip、port及執行路徑 # MySQL 客戶端和 mysqldump 的路徑 MYSQL_CLIENT"/work/oracle/mysql…

【NLP 78、手搓Transformer模型結構】

你以為走不出的淤泥&#xff0c;也遲早會云淡風輕 —— 25.5.31 引言 ——《Attention is all you need》 《Attention is all you need》這篇論文可以說是自然語言處理領域的一座里程碑&#xff0c;它提出的 Transformer 結構帶來了一場技術革命。 研究背景與目標 在 Transfo…

深入理解CSS常規流布局

引言 在網頁設計中&#xff0c;理解元素如何排列和相互作用至關重要。CSS提供了三種主要的布局方式&#xff1a;常規流、浮動和定位。本文將重點探討最基礎也是最常用的常規流布局&#xff08;Normal Flow&#xff09;&#xff0c;幫助開發者掌握頁面布局的核心機制。 什么是…

樹結構詳細介紹(javascript版)

樹結構的基本概念 樹是一種非線性數據結構&#xff0c;由節點和連接節點的邊組成。與線性數據結構&#xff08;如數組、鏈表&#xff09;不同&#xff0c;樹具有層次結構&#xff0c;非常適合表示有層次關系的數據。 樹的基本術語 節點 (Node)&#xff1a; 樹中的基本單元&a…

element-plus bug整理

1.el-table嵌入el-image標簽預覽時&#xff0c;顯示錯亂 解決&#xff1a;添加preview-teleported屬性 <el-table-column label"等級圖標" align"center" prop"icon" min-width"80"><template #default"scope"&g…

RabbitMQ和MQTT區別與應用

RabbitMQ與MQTT深度解析&#xff1a;協議、代理、差異與應用場景 I. 引言 消息隊列與物聯網通信的重要性 在現代分布式系統和物聯網&#xff08;IoT&#xff09;生態中&#xff0c;高效、可靠的通信機制是構建穩健、可擴展應用的核心。消息隊列&#xff08;Message Queues&am…

零基礎遠程連接課題組Linux服務器,安裝anaconda,配置python環境(換源),在服務器上運行python代碼【3/3 適合小白,步驟詳細!!!】

遠程連接服務器 請查閱之前的博客——零基礎遠程連接課題組Linux服務器&#xff0c;安裝anaconda&#xff0c;配置python環境&#xff08;換源&#xff09;&#xff0c;在服務器上運行python代碼【1/3 適合小白&#xff0c;步驟詳細&#xff01;&#xff01;&#xff01;】&am…

Redis最佳實踐——安全與穩定性保障之訪問控制詳解

Redis 在電商應用的安全與穩定性保障之訪問控制全面詳解 一、安全訪問控制體系架構 1. 多層級防護體系 #mermaid-svg-jpkDj2nKxCq9AXIW {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-jpkDj2nKxCq9AXIW .error-ico…

vue2源碼解析——響應式原理

文章目錄 引言數據劫持收集依賴數組處理渲染watchervue3中的響應式 引言 vue的設計思想是數據雙向綁定、數據與UI自動同步&#xff0c;即數據驅動視圖。 為什么會這樣呢&#xff1f;這就不得不提vue的響應式原理了&#xff0c;在使用vue的過程中&#xff0c;我被vue的響應式設…

gcc相關內容

gcc 介紹&#xff1a;linux就是由gcc編譯出來的&#xff0c;而且好像之前Linux只支持gcc編譯。gcc全稱為gnu compiler collection&#xff0c;它是gnu項目的一個組成部分。gnu致力于創建一個完全自由的操作系統&#xff0c;我感覺意思就是完全開源的操作系統。gnu有很多組件和…

android 圖片背景毛玻璃效果實現

圖片背景毛玻璃效果實現 1 依賴 // Glide implementation("com.github.bumptech.glide:glide:4.16.0") kapt("com.github.bumptech.glide:compiler:4.16.0") implementation("jp.wasabeef:glide-transformations:4.3.0") 2 布局<com.googl…

【Java開發日記】你會不會5種牛犇的yml文件讀取方式?

前言 除了爛大街的Value和ConfigurationProperties外&#xff0c;還能夠通過哪些方式&#xff0c;來讀取yml配置文件的內容&#xff1f; 1、Environment 在Spring中有一個類Environment&#xff0c;它可以被認為是當前應用程序正在運行的環境&#xff0c;它繼承了PropertyReso…

Spring Boot事務失效場景及解決方案

事務失效場景1&#xff1a;方法非public修飾 原因 Spring事務基于動態代理&#xff08;AOP&#xff09;實現&#xff0c;非public方法無法被代理攔截&#xff0c;導致事務失效。 代碼示例 Service public class OrderService {Transactionalprivate void createOrder() { //…

電子電路:怎么理解時鐘脈沖上升沿這句話?

時鐘脈沖是數字電路中用于同步各組件操作的周期性信號&#xff0c;通常表現為高低電平交替的方波。理解其關鍵點如下&#xff1a; 時鐘脈沖的本質&#xff1a; 由晶振等元件生成&#xff0c;呈現0/1&#xff08;低/高電平&#xff09;的規律振蕩每個周期包含上升沿→高電平→下…