最短路徑問題(圖論)

1 Floyd

作用:

求圖中所有頂點之間的最短路徑,包括有向圖或者無向圖,權重正負皆可,用來一次性求所有點之間的最短路徑。
思路是 通過逐步擴大中間層,使得最短路徑不斷被更新,直到中間層擴大到n位置,最終所求的就是所有節點都有可能經過的最短距離。

原理

  • 遞推公式,F[K][X][Y] 表示頂點x,y中間最多只經過(0,1,2,…k)這些頂點時的最短路徑
    在這里插入圖片描述

  • 三層遍歷,第一層必須為中間層,這樣才會逐步將中間層擴大,如果中間層沒有放在第一層,會導致 每個f[x] 實際只會求取一次,結果不正確。

  • **根據上面實際上需要使用三位數組進行求解,但是可以優化為二維數組,初始狀態時,時候F[X][Y]可能為 “0/實際權重/正無窮”;如果點X,Y直連,則F[X][Y]為實際權重;如果點X==Y,則F[X][Y]=0;如果點X,Y非直連,則F[X][Y] = 正無窮

實際的代碼如下:

for k in range(1, n + 1):for x in range(1, n + 1):for y in range(1, n + 1):f[k][x][y] = min(f[k - 1][x][y], f[k - 1][x][k] + f[k - 1][k][y])

最外層的數組可以省略,優化為如下:

for k in range(1, n + 1):for x in range(1, n + 1):for y in range(1, n + 1):f[x][y] = min(f[x][y], f[x][k] + f[k][y])

詳見 Floyd算法解析

2 Dijsktra算法

作用

是一種單源最短路徑算法,他能找到其中一個點到其他所有點的最短路徑,只支持權重為正的情況, 因為Dijkstra算法存在貪心的策略,一旦到某個節點的最短路徑被確定,后續就無法修改。故無法支持權重為負的情,其基本的實現策略為貪心+動態更新,
思路:每一步都是從還未處理的節點當中找到離起點最短的節點,然后嘗試用它來更新其周圍鄰居離起點的最短路徑,這樣一步步擴展,直到找到最短路徑。

實現原理

假設有如下圖結構,求節點A到節點F的最短距離,實現過程如下:

  • 首先準備一個優先隊列,一個最短距離前驅表t1,以及visisted存放是否已經i經訪問過。t1[v] = (d, v1)表示頂點A距離頂點v的最短距離d以及頂點v的前驅節點v1,初始的時候,將頂點A到它自身的距離為0,其他頂點到頂點A的距離為無窮大,前驅節點為空,將(0,A)放到優先隊列中(以第一位距離作為排序的key,小根堆)
    在這里插入圖片描述
  • 首先從優先隊列中取出首位距離最短的節點信息(0, A),然后依次遍歷頂點A的所有邊(B,C),將(4, B),(5,C)放到優先隊列中,同時更新最短距離前驅表,并將頂點A放到visited表,表示下次遍歷到頂點A的時候,直接忽略,具體結果如下:
    在這里插入圖片描述
  • 然后再從優先隊列中取出頂點(4, B)信息,依次遍歷B所有的邊(C, D,E)其中A已經被放到visited中,無需再遍歷,遍歷B的邊C的時候,發現權重之和(A->B + B->C =4 + 11 < 5)大于當前表中已經存在的距離,故這里不更新C的距離以及前驅;遍歷邊D的時候,發現(A->B + B-> = 4 + 9 = 13 < 正無窮 )小于當前表中已經存在,更細表中頂點D到A的最短距離為13以及前驅節點為B。
  • 后續的操作與上面一樣,直到優先隊列中的元素被取完在優先隊列中提前碰到目標節點,如果從優先隊列中取出的頂點到A的距離小于表中已經存在的距離或者已經處于visited表中,則直接忽略即可
  • 最后通過得到的最短距離前驅表可以得到頂點A到其他所有節點的最短距離以及對應的路徑
  • 如果只需要求起點到某個終點的最短路徑,則可以在優先隊列中取到目標終點時,可以直接返回,無需再往下處理

備注:最短距離前驅表中前驅信息是用來根據回溯得到目標頂點的最短路徑
代碼實現

def dijkstra(n, source, weights):## weights 列表的每一個元素格式為(n1, n2, w)表示頂點n1->n2的權重為w## n 表示頂點的格式,source表示原頂點## 這里需要將頂點信息都轉化為0,1... n-1的編號# 為求頂點source 到其他頂點的最短距離neighbors = [[] for _ in range(n)]inf = float('inf')edges = [[inf for _ in range(n)] for _ in range(n)]for v1, v2, w in weights:neighbors[v1].append(v2)neighbors[v2].append(v1)edges[v1][v2] = wedges[v2][v1] = wpq = []heapq.heappush(pq, (0, source))visited = set()t1 = {}for i in range(n):t1[i] = (inf, -1)t1[source] = (0, -1)while pq:d, v = heapq.heappop(pq)if d > t1[v][0]:continuevisited.add(v)for p in neighbors[v]:d1 = d + edges[v][p]if p not in visited and (d1 < t1[p][0]):t1[p] = (d1, v)heapq.heappush(pq, (d1, p))return t1if __name__ == '__main__':n = 6source = 0weights = [[0, 1, 4], [0, 2, 5], [1, 2,11], [1, 3, 9], [1, 4, 7], [2, 4, 3], [3, 4, 13], [3, 5, 2], [4, 5, 6]]print(dijkstra(6, 0, weights))

3 Bellman-Ford算法

作用

上面的dijkstra算法只支持權重為正場景,對于有些權值為負的場景需要使用BellmanFord算法,該算法也是求單個頂點到到其余頂點的最短路徑,如果存在負環路徑,則不存在最短路徑
思路:通過不斷的遍歷所有的邊動態的更新到起點的最短距離,不斷地進行松緊操作(迭代),直到n - 1次,確保所有節點到起點均是最短距離。

實現原理

假設有如下圖結構,求節點A到其他節點的最短距離,實現過程如下
在這里插入圖片描述

  • 首先需要準備一個最短路徑前驅表t1, t1[v] 中包含頂點v到頂點A的最短距離以及頂點v的前驅節點。初始的時候 t1[‘A’] = (0, -1) 其他的t[v] = (正無窮,-1)
  • 然后遍歷所有的邊,每遍歷一個邊(v1, v2)的時候,如果當前節點A到v1的t1[v1][0] + 當前邊的權重w(v1->v2)小于當前t1[v2][0],則更新v2的最短距離以及前驅節點
    t1[v1][0] + w(v1->v2) < t1[v2][0]
  • 上面的步驟最多執行n - 1次,如果中間有一次 沒有節點的最短距離需要更新,則說明所有A到所有節點的最短距離已經全部收斂,直接返回。
  • 如果上面執行n- 1次,每次均存在節點的最短距離需要更新,則圖中可能存在負權環,所謂負權環就是如下圖所示,隨著遍歷次數的增加,A到C的距離只會越來越小-2, -3, -4等等,此時說明最短路徑,那么只需要再遍歷第n次,看看是否仍存在某個節點的最短路徑被更新,如果被更新,則該節點存在負權環。
    在這里插入圖片描述
def bellmanFord(n, source, weights):## weights 列表的每一個元素格式為(n1, n2, w)表示頂點n1->n2的權重為w## n 表示頂點的格式,source表示原頂點## 這里需要將頂點信息都轉化為0,1... n-1的編號# 為求頂點source 到其他頂點的最短距離t1 = {}inf = float('inf')for i in range(n):t1[i] = (inf, -1)t1[source] = (0, -1)for i in range(n - 1):for v1, v2, w in weights:if (t1[v1][0] + w) < t1[v2][0]:t1[v2] = (t1[v1][0] + w, v1)# make sure weather negative weight loop existflag, v= False, Nonefor v1, v2, w in weights:if (t1[v1][0] + w) < t1[v2][0]:flag, v = True, v2return t1, flag, vif __name__ == '__main__':n = 6source = 0weights = [[0, 1, 6], [0, 2, 4], [0, 3, 5], [1, 4, -1], [2, 1, -2], [2, 4, 3], [3, 2, -2], [3, 5, -1], [4, 5, 3]]print(bellmanFord(6, 0, weights))

4 A* 算法

作用

用來求兩點之間的最短距離,雖然dijkstra算法也能算法圖,但是如果圖中節點的個數非常多,而且邊也很多,dijkstra算法會找到所有的頂點,根據貪心算法進行排除,然找找到最短的距離。
A* 算法與dijkstra算法類似,可以理解為其是基于dijkstra算法優化而來的,不同的是A* 算法則會借助啟發性搜索,避免一些無效節點的搜索。提高計算效率

思路:
對比dijkstra算法,為了因為啟發性搜索,增加一個預估距離與最短距離加在一起,作為優先隊列的key,每次將為

實現原理

假設有如下圖結構,求節點A到節點F的最短距離,實現過程如下
在這里插入圖片描述

  • 首先準備一個優先隊列,一個最短距離前驅表t1,以及visisted存放是否已經i經訪問過。t1[v] = (g, h ,v2)表示頂點A距離頂點v的最短距離g,頂點A距離頂點v的預估最短距離h,以及頂點v的前驅節點v1,其中(f = g + h)。初始的時候,頂點A到它自身的距離為0,其他頂點到頂點A的距離為無窮大,前驅節點為空,將(d + h,A)放到優先隊列中(以第一位距離d+h 作為排序的key,小根堆)

  • 預估距離,起點到每個頂點都要提前設定一個預估距離,預估距離會作為優先隊列的key的一部分,會影響實際遍歷的順序,預估距離一般由曼哈頓距離或者歐式距離給出,它不作為實際距離,只會影響搜索的方向。可以這樣理解,如果能確認某些節點實際遍歷的時候,大概率是不需要遍歷的,則可以將該節點到起點的預估距離設定的大一些。

  • 首先從優先隊列中取出首位距離最短的節點信息(18, A),然后依次遍歷頂點A的所有邊(B,D),將(15, B),(18,D)放到優先隊列中,同時更新最短距離前驅表中的g項,并將頂點A放到visited表,表示下次遍歷到頂點A的時候,直接忽略,具體結果如下:
    在這里插入圖片描述

  • 然后再從優先隊列中取出頂點(15, B)信息,依次遍歷B所有的邊(C,)其中A已經被放到visited中,無需再遍歷,遍歷B的邊C的時候,發現權重之和(A->B + B->C =3 + 6 < 正無窮)小于當前表中已經存在的距離,故這里需要更新C的距離以及前驅,并將節點(9 + 7, C)放到優先隊列中。

  • 后續的操作與上面一樣,直到優先隊列中的元素被取完在優先隊列中提前碰到目標節點,如果從優先隊列中取出的頂點到A的距離小于表中已經存在的距離或者已經處于visited表中,則直接忽略即可

  • 最后通過得到的最短距離前驅表可以得到頂點A到其他所有節點的最短距離以及對應的路徑

  • 如果只需要求起點到某個終點的最短路徑,則可以在優先隊列中取到目標終點時,可以直接返回,無需再往下處理

def aStar(n, source, weights):## weights 列表的每一個元素格式為(n1, n2, w)表示頂點n1->n2的權重為w## n 表示頂點的格式,source表示原頂點## 這里需要將頂點信息都轉化為0,1... n-1的編號# 為求頂點source 到其他頂點的最短距離neighbors = [[] for _ in range(n)]inf = float('inf')edges = [[inf for _ in range(n)] for _ in range(n)]for v1, v2, w in weights:neighbors[v1].append(v2)neighbors[v2].append(v1)edges[v1][v2] = wedges[v2][v1] = wpq = []g = {0: 18, 1: 12, 2: 7, 3: 11, 4: 5, 5: 0}visited = set()t1 = {}for i in range(n):t1[i] = (inf, g[i], -1)t1[source] = (0, g[source], -1)heapq.heappush(pq, (t1[0][0] + t1[0][0], source))while pq:f, v = heapq.heappop(pq)if f > (t1[v][0] + t1[v][1]) :continuevisited.add(v)for p in neighbors[v]:g1 = t1[v][0] + edges[v][p]if p not in visited and (g1 < t1[p][0]):t1[p] = (g1, t1[p][1], v)heapq.heappush(pq, (g1 + t1[p][1], p))return t1if __name__ == '__main__':n = 6source = 0weights = [[0, 1, 3], [0, 3, 7], [1, 2, 6], [2, 3, 8], [2, 4, 7], [2, 5, 10], [3, 4, 11], [4, 5, 7]]print(aStar(6, 0, weights))

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

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

相關文章

2025年8月新算法—云漂移優化算法(Cloud Drift Optimization Algorithm, CDO)

1、簡介 這項研究介紹了云漂移優化&#xff08;數位長&#xff09;算法&#xff0c;這是一種創新的自然啟發的元啟發式方法來解決復雜的優化問題。CDO模仿受大氣力影響的云粒子的動態行為&#xff0c;在探索和利用之間取得了微妙的平衡。它具有自適應權重調整機制&#xff0c;可…

VS Code進行.NET開發時使用斷點和熱重載

VS Code 調試熱重載 1. VS Code 設置 安裝擴展&#xff1a;C#、C# Dev Kit設置中搜索hot reload&#xff0c;選擇C#開發工具包&#xff0c;把下圖的幾項全部打勾2. 啟動項目&#xff08;僅用左側“運行和調試”&#xff09; 打開解決方案&#xff0c;選你的啟動項目的“.NET La…

mysqlbinlog解析命令

解析 MySQL Binlog 詳細信息的命令以下是解析 MySQL Binlog 詳細信息的常用命令&#xff1a;1. 基本 binlog 解析命令# 查看 binlog 文件內容&#xff08;基本格式&#xff09; mysqlbinlog /var/lib/mysql/mysql-bin.000001# 查看特定時間段的 binlog mysqlbinlog --start-dat…

算法訓練營day60 圖論⑩ Bellman_ford 隊列優化算法、判斷負權回路、單源有限最短路(修改后版本)

增加對最短路徑的優化算法、負權回路、單源有限最短的講解 Bellman_ford 隊列優化算法 -------------------------------------------------------------------------------- 8.24更新&#xff1a;該算法是針對帶負值的最短路徑的優化算法&#xff0c;核心通過隊列來實現&…

Python 學習(十六) 下一代 Python 包管理工具:UV

目錄1. UV 介紹1.1 什么是UV&#xff1f;1.2 UV的核心優勢1.3 UV和其他工具對比1&#xff09;UV vs. pipvirtualenv2&#xff09;UV vs. Conda3&#xff09;UV vs. Poetry4&#xff09;功能對比表2. UV的安裝與常用命令2.1 安裝UV1&#xff09;使用官方安裝腳本&#xff08;推薦…

Redis學習筆記 ----- 緩存

一、什么是緩存 緩存&#xff08;Cache&#xff09;是數據交換的緩沖區&#xff0c;是存儲數據的臨時地方&#xff0c;一般讀寫性能較高。 &#xff08;一&#xff09;緩存的作用 降低后端負載&#xff1a;減少對數據庫等后端存儲的直接訪問壓力。提高讀寫效率&#xff0c;降低…

React響應式鏈路

文章目錄響應式鏈路的核心環節1.狀態定義與初始化2.狀態更新觸發&#xff08;狀態變更&#xff09;3.調度更新&#xff08;Scheduler&#xff09;4.重新渲染&#xff08;Render 階段&#xff09;5.協調&#xff08;Reconciliation&#xff09;與 Fiber 架構6.提交更新&#xff…

軟件設計師——計算機網絡學習筆記

一、計算機網絡 網絡基礎 1. 計算機網絡的分類2. 網絡拓撲結構 總線型(利用率低、干擾大、價格低) 星型(交換機形成的局域網、中央單元負荷大) 環型(流動方向固定、效率低擴充難) 樹型(總線型的擴充、分級結構) 分布式(任意節點連接、管理難成本高)一般來說&#xff0c;辦公室局…

1200 SCL學習筆記

一. IF. 如果。下面是一個起保停IF #I_start AND NOT #I_stop THEN //如果I_start接通 和 I_stop沒有接通#Q_run : 1; //輸出Q_run 接通 ELSIF #I_stop THEN //如果I_stop接通#Q_run : 0; //。。。。。。 END_IF;二. CASECASE…

單例模式與線程池

1. 單例模式單例模式是一種常用的設計模式&#xff0c;它確保一個類只有一個實例&#xff0c;并提供一個全局訪問點來獲取這個實例。這種模式在需要控制資源訪問、管理共享狀態或協調系統行為時非常有用。單例模式的核心特點&#xff1a;私有構造函數&#xff1a;防止外部通過n…

Chrome和Edge如何開啟暗黑模式

Edge和Chrome瀏覽器都提供了實驗性功能&#xff0c;可以通過修改實驗性設置來開啟暗黑模式。 在瀏覽器地址欄中輸入edge://flags/&#xff08;Edge&#xff09;或chrome://flags/&#xff08;Chrome&#xff09;。在搜索框中輸入“dark”&#xff0c;找到與暗黑模式相關的選項。…

【科研繪圖系列】浮游植物的溶解性有機碳與初級生產力的關系

禁止商業或二改轉載,僅供自學使用,侵權必究,如需截取部分內容請后臺聯系作者! 文章目錄 介紹 數據準備 數據處理 溶解性有機碳(DOC)與初級生產力(NPP)的關系 溶解性有機碳(DOC)與光照強度(PAR)的關系 數據可視化 加載R包 數據下載 導入數據 畫圖1 畫圖2 總結 系統信…

IDEA相關的設置和技巧

IDEA相關的設置和技巧 我的博客對應文章地址 1.布局設置 IDEA的布局自定義程度很高&#xff0c;頂部工具欄&#xff0c;側邊欄都可以隨意定制&#xff0c;設置好的布局方案可以保存&#xff0c;在新項目中快速使用 1.1 工具欄設置 [!tip] 舉個例子&#xff1a;比如我要在頂部…

AWS Lambda 完全指南:解鎖無服務器架構的強大力量

在云計算的發展浪潮中,無服務器(Serverless) 架構已然成為構建現代應用的新范式。而在這場變革的中心,AWS Lambda 作為開創性的 Function-as-a-Service (FaaS) 服務,徹底改變了我們部署和運行代碼的方式。 本文將帶您深入探索 AWS Lambda,從核心概念、工作原理到高級實踐…

人工智能時代下普遍基本收入(UBI)試驗的實踐與探索——以美國硅谷試點為例

一、硅谷UBI試驗的最新進展&#xff08;2025年&#xff09;1. 試驗規模與資金來源圣克拉拉縣試點&#xff1a;硅谷所在地圣克拉拉縣針對脫離寄養家庭的年輕人開展UBI試驗&#xff0c;每月發放1000美元補貼&#xff0c;持續1-2年&#xff0c;覆蓋約60名參與者&#xff0c;成本約…

云計算之云主機Linux是什么?有何配置?如何選?

一、云環境如何選擇Linux發行版 1.1、Linux在各個領域的發展 Linux在各個領域的發展序號Linux發展領域說明1Linux在服務器領域的發展目前Linux在服務器領域已經占據95%的市場份額&#xff0c;同時Linux在服務器市場的迅速崛起&#xff0c;已經引起全球IT產業的高度關注&#xf…

XCVU13P-2FHGB2104E Xilinx(AMD)Virtex UltraScale+ FPGA

XCVU13P-2FHGB2104E 是 Xilinx&#xff08;AMD&#xff09;Virtex UltraScale FPGA 系列中的一款高性能芯片&#xff0c;適用于需要大量邏輯資源、高帶寬和高速數據傳輸的應用場景。作為該系列中的旗艦產品&#xff0c;XCVU13P-2FHGB2104I 結合了強大的處理能力和靈活的可編程性…

自動化單詞例句獲取系統設計方案

方案一 (網絡爬蟲) 這個方案的核心思路是:創建一個自動化的腳本,該腳本會讀取你 MongoDB 中的單詞,然后去一個免費的在線詞典網站上抓取這些單詞的例句,最后將抓取到的例句存回你的 MongoDB 數據庫中對應的單詞條目下。 一、 核心思路與技術選型 自動化腳本: 我們將使用 P…

WPF Alert彈框控件 - 完全使用指南

WPF Alert彈框控件 - 完全使用指南概述快速開始nuget安裝與引用基本用法功能特性詳細說明AlertType 枚舉方法參數詳解Show 方法&#xff08;局部彈窗&#xff09;ShowGlobal 方法&#xff08;全局彈窗&#xff09;完整示例代碼XAML 布局C# 代碼實現界面演示功能特性對比表格自定…

可視化-模塊1-HTML-01

1-軟件下載&#xff1a; 軟件名稱&#xff1a;HBuilderX 官網地址&#xff1a; https://www.dcloud.io/hbuilderx.html 下載文佳-解壓縮-打開exe文件 創建快捷方式至桌面 2-創建項目 【普通項目】-【基本HTML項目】-【項目名&#xff1a;week1-1】 【index】輸入&#xff1…