代碼隨想錄算法訓練營Day64|拓撲排序(卡碼網117)、dijkstra樸素版

拓撲排序

117. 軟件構建 (kamacoder.com)

拓撲排序簡單的說是將一個有向圖轉為線性的排序

它將圖中的所有結點排序成一個線性序列,使得對于任何的邊uv,結點u在序列中都出現在結點v之前,這樣的序列滿足圖中所有的前驅-后繼關系。

拓撲排序通常用于任務調度、項目計劃、編譯依賴分析等場景,其中活動或任務之間存在依賴關系,需要確定一個合理的執行順序。

拓撲排序的算法步驟如下:

  1. 選擇一個沒有前驅的結點(即入度為0的結點),將其加入到拓撲排序的序列中,并從圖中刪除該節點及其所有出邊。
  2. 重復步驟1,直到所有的結點都被加入拓撲排序序列中或者途中不再存在無前驅的結點。
  3. 如果所有的結點都被加入序列中,則完成了拓撲排序;若圖中還存在結點,則說明圖中存在環,無法進行拓撲排序。

????????由于拓撲排序的結果可能不唯一,當圖中存在多個入度為0的結點,可以任意選擇一個結點進行刪除

在實際應用中,拓撲排序通常和深度優先搜索或廣度優先搜素結合使用。例如,使用廣度優先搜索(拓撲排序的廣度優先搜索實現通常被稱為Kahn算法)進行拓撲排序的算法流程如下:

  1. 計算所有節點的入度:遍歷圖中的所有節點,計算每個節點的入度(即有多少邊指向該節點)。

  2. 初始化隊列:創建一個空隊列,將所有入度為0的節點加入隊列。這些節點是沒有前置依賴的節點,可以開始執行。

  3. 處理隊列:只要隊列不為空,就重復以下步驟:

    • 從隊列中取出一個節點(稱為當前節點),并將其添加到拓撲排序的結果序列中。
    • 減少當前節點的所有出邊指向的節點的入度(因為這些節點的依賴減少了)。
    • 如果某個節點的入度在減少后變為0,則將其加入隊列,因為它現在沒有前置依賴了。
  4. 檢查是否有未處理的節點:當隊列為空時,如果所有的節點都已經添加到拓撲排序的結果序列中,則拓撲排序成功完成。如果還有節點未添加到結果序列中,則說明圖中存在環,因此無法進行拓撲排序。

偽代碼

拓撲排序(圖 G):初始化入度為0的隊列 Q初始化拓撲排序的結果序列 L// 計算所有節點的入度對于每個節點 v in G:v.入度 = G 中指向 v 的邊的數量如果 v.入度 == 0:Q.enqueue(v)// 處理隊列當 Q 不為空時:當前節點 u = Q.dequeue()L.add(u)  // 將 u 添加到拓撲排序的結果序列中// 減少所有出邊的目標節點的入度對于每個節點 v,其中存在邊 u -> v:v.入度 = v.入度 - 1如果 v.入度 == 0:Q.enqueue(v)// 檢查是否所有節點都已處理如果 L 中的節點數量不等于 G 中的節點數量:返回 "圖 G 包含環,無法進行拓撲排序"否則:返回 L 作為拓撲排序的結果序列

C++代碼參考代碼隨想錄代碼隨想錄 (programmercarl.com)

#include <iostream>
#include <vector>
#include <queue>
#include <unordered_map>
using namespace std;int main() {int N, M; // N個文件存在M條依賴關系cin >> N >> M;vector<int> inDegree(N, 0); // 記錄每個點的入度unordered_map<int, vector<int>> umap;// 讀取M條依賴關系for (int i = 0; i < M; i++) {int s, t;cin >> s >> t;// t依賴于s,因此t的入度加1inDegree[t]++;umap[s].push_back(t);}queue<int> Queue;// 將所有入度為0的節點加入隊列for (int i = 0; i < N; i++) {if (inDegree[i] == 0)Queue.push(i);}vector<int> path; // 存儲拓撲排序結果while (!Queue.empty()) {int cur = Queue.front();Queue.pop();path.push_back(cur);// 遍歷當前節點的所有后繼節點for (int next : umap[cur]) {inDegree[next]--;if (inDegree[next] == 0)Queue.push(next);}}// 檢查是否所有的節點都被處理了if (path.size() == N) {for (int i = 0; i < N - 1; i++) {cout << path[i] << " ";}cout << path[N - 1];} else {// 如果不是所有的節點都被處理,說明存在環cout << -1 << endl;}return 0;
}

在時間復雜度上,初始化入度數組O(N),讀取依賴關系并構建鄰接表O(M)(M條依賴關系),將入度為0結點加入隊列,O(N),BFS的時間復雜度為O(N+M)(每個結點最多訪問一次,每個結點被加入隊列后移除,每條邊會被訪問一次來減少相鄰結點的入度)時間復雜度為O(N+M)

空間復雜度 入度數組O(N),鄰接表最差情況下O(N^2),隊列和路徑數組都為O(N),最差情況下空間復雜度為O(N^2),但實際應用中,若圖比較稀疏,則空間復雜度為O(M+N)。

dijkstra

47. 參加科學大會(第六期模擬筆試) (kamacoder.com)

????????Dijkatra算法是一種著名的圖搜索算法,它用于在加權圖中找到從一源節點到其余所有結點的最短路徑。

算法步驟:

  1. 初始化:需要一個最短路徑估計的容器(優先隊列,通常是最小堆)存儲所有結點及其當前的最短路徑估計值,除源節點設置為0外,將所有結點的最短路徑估計值設置為無窮大。
  2. 訪問源結點:將源結點加入優先隊列。
  3. 循環處理隊列:當優先隊列非空時,重復以下步驟:

    從優先隊列中取出具有最小估計值的節點,稱為當前節點

    對于當前節點的每個鄰接節點,執行以下操作:

    1. 計算通過當前節點到達鄰接節點的路徑長度。
    2. 如果這個路徑長度比已知的最短路徑估計值更短,則更新鄰接節點的最短路徑估計值,并更新它的前驅節點為當前節點。
    3. 將鄰接節點及其新的最短路徑估計值加入優先隊列。?
  4. 標記完成:當一個結點從優先隊列取出時,意味著它的最短路徑已經確定,可以將其標記為完成。
  5. 構建最短路徑樹:當算法結束時,可以從源結點開始,通過每個結點的前驅結點信息,構造出從源結點到所有其他結點的最短路徑樹。

需要注意的幾個點:

  • Dijkstra算法不能處理帶有負權邊的圖,因為在有負權邊的圖中,可能存在一條路徑,其總權重隨著經過的邊數增加而減少,導致無法正確找到最短路徑。
  • Dijkstra算法的時間復雜度為O(V^2),V為圖中結點的數量,使用優先隊列可以優化到O(E+VlogV),E為邊的數量、
  • Dijkstra可以用于有向圖和無向圖。

代碼隨想錄 (programmercarl.com)

#include <iostream>
#include <vector>
#include <climits>
using namespace std;int main() {int N, M; // N個文件存在M條依賴關系cin >> N >> M;vector<vector<int>> grid(N+1, vector<int>(N+1, INT_MAX)); // 創建一個N+1xN+1的二維數組,用于存儲節點之間的權重,初始化為INT_MAXint v1, v2, val;for (int i = 0; i < M; i++) { // 讀取M條依賴關系cin >> v1 >> v2 >> val; // 讀取兩個節點v1和v2以及它們之間的權重valgrid[v1][v2] = val; // 更新權重矩陣,表示v1到v2有邊,權重為val}int start = 1; // 定義起始節點為1int end = N; // 定義目標節點為Nvector<int> minDist(N+1, INT_MAX); // 創建一個長度為N+1的數組,用于存儲從起始節點到其他節點的最短路徑估計值,初始化為INT_MAXvector<int> visited(N+1, 0); // 創建一個長度為N+1的數組,用于標記節點是否被訪問過,0表示未訪問,1表示已訪問minDist[start] = 0; // 起始節點到自身的最短路徑為0for (int i = 0; i <= N; i++) { // 循環,找到未訪問的最短路徑節點int minVal = INT_MAX; // 初始化最小值為INT_MAXint cur = 1; // 初始化當前節點為1for (int v = 1; v <= N; v++) { // 遍歷所有節點,找到未訪問且最短路徑估計值最小的節點if (!visited[v] && minDist[v] < minVal) { // 如果節點v未訪問且最短路徑估計值小于minValminVal = minDist[v]; // 更新最小值cur = v; // 更新當前節點為v}}visited[cur] = 1; // 標記當前節點為已訪問for (int v = 1; v <= N; v++) { // 遍歷所有節點,更新從當前節點出發到其他節點的最短路徑估計值if (!visited[v] && grid[cur][v] != INT_MAX && minDist[cur] + grid[cur][v] < minDist[v]) {// 如果節點v未訪問,且當前節點到節點v有邊,且通過當前節點到達v的路徑更短minDist[v] = minDist[cur] + grid[cur][v]; // 更新節點v的最短路徑估計值}}}if (minDist[end] == INT_MAX) // 如果目標節點的最短路徑估計值仍然是INT_MAX,表示沒有路徑到達目標節點cout << -1 << endl; // 輸出-1elsecout << minDist[end] << endl; // 否則輸出從起始節點到目標節點的最短路徑長度return 0;
}

算法的時間復雜度為O(N^2),空間復雜度這里也是O(N^2)(沒有用上最小堆等優先隊列)

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

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

相關文章

vue 插槽 【slot】

文章目錄 默認插槽具名插槽作用域插槽 默認插槽 父組件中&#xff1a;<Category title"今日熱門游戲"><ul><li v-for"g in games" :key"g.id">{{ g.name }}</li></ul></Category> 子組件中&#xff1a;<…

9. 機器人數目

題目描述 本題為填空題&#xff0c;只需要算出結果后&#xff0c;在代碼中使用輸出語句將所填結果輸出即可。 少年宮新近郵購了小機器人配件&#xff0c;共有3類。 &#x1d434;A 類含有&#xff1a;88 個輪子&#xff0c;11 個傳感器&#xff1b; &#x1d435;B 類含有:…

深入理解基本數據結構:棧詳解

引言 在計算機科學中&#xff0c;數據結構是存儲、組織和管理數據的方式。棧是一種重要的線性數據結構&#xff0c;廣泛應用于各種編程場景。在這篇博客中&#xff0c;我們將詳細探討棧的定義、特點、操作及其在不同編程語言中的實現。 什么是棧&#xff1f; **棧&#xff08…

java動態代理的使用和代碼示例

文章目錄 1. 簡介2. 代碼3. 參考鏈接 1. 簡介 代理類在程序運行時創建的代理方式被成為動態代理。在靜態代理中&#xff0c;代理類&#xff08;RenterProxy&#xff09;是自己已經定義好了的&#xff0c;在程序運行之前就已經編譯完成。而動態代理是在運行時根據我們在Java代碼…

前端vue 實現取色板 的選擇

大概就是這樣的 一般的web端框架 都有自帶的 的 比如 ant-design t-design 等 前端框架 都是帶有這個的 如果遇到沒有的我們可以自己嘗試開發一下 簡單 的 肯定比不上人家的 但是能用 能看 說的過去 我直接上代碼了 其實這個取色板 就是一個input type 是color 的input …

CTF學習記錄(一)——Web基礎

目錄 Web基礎Web基礎常用工具ncat(網絡工具中的瑞士軍刀&#xff0c;功能齊全)curl(一個工作在命令行的發起HTTP請求的工具)BurpSuite(Web核心抓包工具)Hackbar插件SwitchyOmega 代理插件&#xff08;非常牛逼&#xff09;Wappalyzer 技術判斷插件EditThisCookie 插件Postman 接…

深入理解Spring Boot中的定時任務調度

深入理解Spring Boot中的定時任務調度 大家好&#xff0c;我是微賺淘客系統3.0的小編&#xff0c;也是冬天不穿秋褲&#xff0c;天冷也要風度的程序猿&#xff01; 1. Spring Boot中的定時任務概述 在現代應用程序開發中&#xff0c;定時任務調度是一項非常常見和重要的功能…

【計算機網絡03】不花錢怎么搭建一個網絡實驗室

使用GNS3和虛擬機搭建網絡實驗室 1、安裝抓包工具分析數據包2、定義和使用抓包篩選器3、安裝和配置GNS34、配置路由器和VPCS5、使用WireShark捕獲GNS3網絡數據包6、VMware創建虛擬機7、使用思科PacketTracer 1、安裝抓包工具分析數據包 官網安裝wireshark&#xff1a;https://…

python怎么判斷字符串以什么結尾

在python編輯器中新建一個data.py。 寫上自己的注釋。 然后新建一個變量testname。 利用endswith來判斷字符串是不是以“ar”結尾。 將結果打印出來。 選擇“run”->“run”。 運行該程序&#xff0c;如果是&#xff0c;就會返回true。

JavaScript-日期對象

日期對象 作用&#xff1a;用來表示時間的對象 獲取當前時間 const datenew Date();console.log(date);可以得到日期對象&#xff0c;里面的屬性有星期&#xff0c;年月日&#xff0c;時分秒 獲取指定時間 const datenew Date(2023-05-01);console.log(date); 獲取時間戳 時間…

PyTorch深度學習實戰(45)——強化學習

PyTorch深度學習實戰&#xff08;45&#xff09;——強化學習 0. 前言1. 強化學習基礎1.1 基本概念1.2 馬爾科夫決策過程1.3 目標函數1.4 智能體學習過程 2. 計算狀態值3. 計算狀態-動作值4. Q 學習4.1 Q 值4.2 Gym環境4.3 構建 Q 表4.4 探索-利用策略 小結系列鏈接 0. 前言 強…

悠律凝聲環開放式耳機體驗:強勁低音、高顏值設計

最近發現了一款潮酷的開放式耳機&#xff0c;不僅顏值抗打&#xff0c;更重要的是能在嘈雜的環境中提供給我一份寧靜的沉浸式音樂體驗&#xff0c;號稱是開放音頻中的重低音之王&#xff0c;它就是悠律凝聲環開放式耳機。 這款耳機無論其外觀設計、音質效果、性價比以及續航能力…

通勤數據:Comma2k19 數據集

A Commute in Data: The comma2k19 Dataset 通勤數據&#xff1a;Comma2k19 數據集 https://arxiv.org/pdf/1812.05752v1 Abstract— comma.ai presents comma2k19, a dataset of over 33 hours of commute in California’s 280 highway. This means 2019 segments, 1 minut…

js實現尋找數組中滿足某個條件的對象,以及找到下標后,在數組中插入某個對象

let ItemIndex fileList.findIndex((item) > { return item.xxx 你要找的屬性值 }); if(ItemIndex > -1){ // 代表找到了這個元素 } else { } 參考百度AI: 在JavaScript中&#xff0c;?可以使用splice()方法在指定位置插入一個或多個對象到數組…

npm、cnpm、pnpm、yarn的區別

npm, cnpm, pnpm, 和 yarn 都是 JavaScript 的包管理工具&#xff0c;用于自動化處理包的安裝、更新、配置和管理。它們之間的主要區別在于它們各自的實現方式、性能優化、以及一些特有的功能。 npm npm (Node Package Manager) 是 Node.js 的默認包管理器&#xff0c;也是最…

「媒體邀約」上海請媒體的費用

傳媒如春雨&#xff0c;潤物細無聲&#xff0c;大家好&#xff0c;我是51媒體網胡老師。 上海無疑是最具活動的城市之一&#xff0c;各種大大小小的論壇、發布會、展覽展會應接不暇&#xff0c;那么在上海做活動想邀請媒體進行宣傳報道&#xff0c;需要多少費用呢&#xff1a;…

Android --- 運行時Fragment如何獲取Activity中的數據,又如何將數據傳遞到Activity中呢?

1.通過 getActivity() 方法獲取 Activity 實例&#xff1a; 在 Fragment 中&#xff0c;可以通過 getActivity() 方法獲取當前 Fragment 所依附的 Activity 實例。然后可以調用 Activity 的公共方法或者直接訪問 Activity 的字段來獲取數據。 // 在 Fragment 中獲取 Activity…

手慢無,速看︱PMO大會內部學習資料

全國PMO專業人士年度盛會 每屆PMO大會&#xff0c;組委會都把所有演講嘉賓的PPT印刷在了會刊里面&#xff0c;供大家會后回顧與深入學習。 第十三屆中國PMO大會-會刊 《2024第十三屆中國PMO大會-會刊》 &#xff08;內含演講PPT&#xff09; 會刊&#xff1a;750個頁碼&…

代碼隨想錄-DAY④-鏈表——leetcode 24 | 19 | 142

24 思路 如果 pre 的后面沒有節點或者只有一個節點&#xff0c;則沒有更多的節點需要交換, 否則&#xff0c;通過更新節點的指針關系交換 pre 后面的兩個節點&#xff0c; 最后&#xff0c;返回新的鏈表的頭節點 dummyhead->next。 時間復雜度&#xff1a;O(n) 空間復雜…

buuctf面具下的flag

細節: 這道題可能因為是vmdk的原因 導致在window上 7z無法得到全部的信息 所以最后解壓要在linux系統上 解密網站 Brainfuck/Ook! Obfuscation/Encoding [splitbrain.org] 這道題010打開,可以發現里面隱藏了很多 binwalk解壓 兩個文件 vmdk可以直接 用7z解壓 7z x flag.…