最短路徑——Dijkstra算法以及二叉堆優化(含證明)

一般最短路徑算法習慣性的分為兩種:單源最短路徑算法和全頂點之間最短路徑。前者是計算出從一個點出發,到達所有其余可到達頂點的距離。后者是計算出圖中所有點之間的路徑距離。


單源最短路徑

Dijkstra算法

思維

本質上是貪心的思想,聲明一個數組dis來保存源點到各個頂點的最短距離和一個保存已經找到了最短路徑的頂點的集合:S,原本的元素構成集合Q,初始時,原點 s 的路徑權重被賦為 0 (dis[s] = 0)。若對于頂點 s 存在能直接到達的邊(s,m),則把dis[m]設為w(s, m),同時把所有其他(s不能直接到達的)頂點的路徑長度設為無窮大。初始時,集合S只有頂點s

然后,從dis數組選擇最小值,則該值就是源點s到該值對應的頂點的最短路徑,并且把該點加入到S中,此時完成一個頂點, 然后,我們需要看看新加入的頂點是否可以到達其他頂點并且看看通過該頂點到達其他點的路徑長度是否比源點直接到達短,如果是,那么就替換這些頂點在dis中的值。 然后,又從dis中找出最小值,重復上述動作,直到S中包含了圖的所有頂點。
但是很可惜,由于算法特性,一個點的距離確定后不會再改變,這里的確定不是指得到數值,而且該點被作為觀察點觀察后所以這個算法并不能處理帶負權邊的圖。

但是可以利用該算法+優先隊列來優化,優化后的算法打破了之前的一個點的距離確定后不會再改變的算法特性,更加類似SPFA,并且可以處理負權邊。但個人覺得已經不能稱作dijkstra算法了。


證明

這里給出一個命題:從集合Q中找到dis[k]最小的v,dis[k]即為源點到v的最短路徑長度。
如果這個命題為真,dij的正確性就可以得證。

  • 證明:從開始利用算法取得一個v1,即dis[v1]是最小的,\(\forall\)v,dis[v]>dis[v1]。
    假設dis[v1]不是從源點到v1最短路徑
    \(\exists\)v,使得dis[v]<dis[v1],與已知矛盾。
    得證。
  • 證明:已利用算法從Q中找到k個點,并確定了k個點的最短路徑,此時再從Q中用算法找出一個vk+1,dis[vk+1]即為源點到vk+1最短路徑。
    假設dis[vk+1不是源點到vk+1的最短路徑長度。
    則設從源點到vk+1的最短路徑經過的點的集合為V,dis為路徑長度,切dis < dis[vk+1]。
    設V中最靠近vk+1且不屬于S的點為vx,vx的后繼點為vy
    。如果有向圖中皆為正權邊,則易得dis[vx] < dis[vy] <= dis。(vy = vk+1時等號成立)
    但又因為vx不屬于S,則dis[vx] > dis,矛盾。
    得證。
  • 綜上所述,命題得證。
  • 負權邊的時候,dis[vx] < dis[vy]和dis[vx] > dis都不一定成立。故不得證。

舉例演算

1329608-20181205220923542-618666981.png

集合S當前觀察點udis[2]dis[3]dis[4]dis[5]dis[6]
1-12
1,221246
1,2,4415246
1,2,4,5515246
1,2,4,5,3315245
1,2,4,5,3,6615245

從結點1出發,1與2、4連通,確定(1,2),(1,4)的距離,其中到2的距離最短,再從觀察點2出發,2與5、6連通,根據dis[u]+c[u][v]<dis[v]的判斷關系出發,更新dis。接著再分別從觀察點4,5,3,6出發更新dis,得到最終的結點1的單源最短路徑。


代碼實現

樸素dij算法,時間復雜度約為O(n2)

#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>using namespace std;const int maxn = 1000;
const int inf = 0x7fffffff;int n, m;
int e[maxn][maxn], dis[maxn];
int book[maxn];void dij(int s) {for (int i = 1; i <= n; i++) dis[i] = e[s][i];for (int i = 1; i <= n; i++) book[i] = 0;book[s] = 1;dis[s] = 0;for (int i = 1; i <= n - 1; i++) {int min = inf;int u;for (int j = 1; j <= n; j++) {if (book[j] == 0 && dis[j] < min) {min = dis[j];u = j;}}book[u] = 1;for (int v = 1; v <= n; v++) {if (e[u][v] < inf && book[v] == 0) {if (dis[v] > dis[u] + e[u][v]) {dis[v] = dis[u] + e[u][v];}}}}
}int main() {cin >> n >> m;for (int i = 1; i <= n; i++) {for (int j = 1; j <= n; j++) {e[i][j] = inf;}}for (int i = 0; i < m; i++) {int u, v, w;cin >> u >> v >> w;e[u][v] = w;}int x;cin >> x;dij(x);for (int i = 1; i <= n; i++) {cout << dis[i] << " ";}return 0;
}

為了能夠方便的尋找當前最小的dis作為觀察點,可以利用優先隊列最小堆來優化。同時利用初始化建表來節省尋找每個點的相鄰點的過程。這里使用的是stl中的優先隊列,底層是heap實現的,應該是二叉堆,所以時間復雜度應該是O((m+n)logn),如果是使用斐波那契堆,可以到O(nlogn)。

#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>using namespace std;const int MAX = 1000;int h[MAX * 2], to[MAX * 2], nxt[MAX * 2], co[MAX * 2], dis[MAX], k = 0, n, m;
priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > que;void insert(int u,int v,int c) {nxt[++k] = h[u];h[u] = k;to[k] = v;co[k] = c;nxt[++k] = h[v];h[v] = k;to[k] = u;co[k] = c;
}void dij(int s) {for (int i = 0; i < MAX; i++) dis[i] = 0x7FFFFFFF;dis[s] = 0;que.push(make_pair(dis[s], s));while (!que.empty()) {pair<int, int> u = que.top();que.pop();if (dis[u.second] < u.first) continue;for (int i = h[u.second]; i; i = nxt[i]) {if (dis[to[i]] > dis[u.second] + co[i]) {dis[to[i]] = dis[u.second] + co[i];que.push(make_pair(dis[to[i]], to[i]));}}}
}int main() {cin >> n >> m;memset(h, 0, sizeof(h));int u, v, c;for (int i = 0; i < m; i++) {cin >> u >> v >> c;insert(u, v, c);}int x;cin >> x;dij(x);for (int i = 1; i <= n; i++) {if (dis[i] > 100000) cout << "none" << " ";else cout << dis[i] << " ";}cout << endl;return 0;
}

轉載于:https://www.cnblogs.com/pullself/p/10073785.html

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

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

相關文章

linux shmget shmctl

shmgetint shmget(key_t key, size_t size, int flag);key: 標識符的規則size:共享存儲段的字節數flag:讀寫的權限返回值&#xff1a;成功返回共享存儲的id&#xff0c;失敗返回-1key_t key----------------------------------------------- key標識共享內存的鍵值: 0/IPC_P…

java控制臺輸入輸出總結

一、控制臺輸入&#xff1a; 1.最常用&#xff1a;Scanner public static void main(String[] args) { System.out.println("請輸入數據:"); Scanner scan new Scanner(System.in); String read scan.nextLine(); System.out.println("輸入的數據為:"…

伯克利開源工具庫RLib現已支持大規模多智能體強化學習

AI前線導讀&#xff1a;近日&#xff0c;UC伯克利的研究團隊RISELab在其Github的項目Ray Rlib 0.6.0中添加了面向多智能體強化學習&#xff08;multi-agent Reinforcement Learning&#xff09;的支持。本文由團隊成員Eric Liang首發于RISELab團隊主頁&#xff0c;AI前線翻譯整…

相機電子快門和機械快門有什么區別

https://zhidao.baidu.com/question/9178007.html

Long

而由于javascript數字的最大值2的53次方-1&#xff0c;以及PHP的數字處理能力&#xff0c;比如number_format(9027199254740993, 0, , )轉載于:https://www.cnblogs.com/sfsdst/p/6734083.html

操作系統實驗以及課程設計

趁沒人&#xff0c;當個小白來偷偷摸摸補一下操作系統的課程&#xff0c;羞反正操作系統斷斷續續的看了一點了&#xff0c;主要是偏linux的。FreeBSD的實現&#xff0c;操作系統概念&#xff0c;30天自制操作系統等。Linux的話命令用的還行&#xff0c;沒有很深入的搞。看操作系…

關于星光級和低照度你了解多少?

http://www.tpy888.cn/news/201607/22/89214.html

AI界的妖風

最近一篇文章https://zhuanlan.zhihu.com/p/50948707深度學習碰上古文獻&#xff0c;西南大學提出基于CNN的古彝文識別方法 我預計不久之后就會出現一個現象&#xff1a;不光有彝族文字識別&#xff0c;還有蒙文識別&#xff0c;藏文識別&#xff0c;苗文識別 然后各位教授一起…

poj1936

非連續子串匹配題&#xff0c;直接模擬 /** \brief poj 1936** \param date 2014/8/5* \param state AC* \return memory 804k time 0ms**/#include <iostream> #include <fstream> #include <cstring>using namespace std;const int MAXN100000; char s[MAX…

Process和ProcessBuilder入門【原】

ProcessBuilder優點 ProcessBuilder(XXX).start()和Runtime.exec(XXX)功能相同,主要優點在使用過程中感受有: 前者是jdk1.5后的新方式配置環境變量時更優雅對當前目錄的控制也更合理錯誤流重定向特別方便 進程控制更簡潔ProcessTool.java package test;import java.io.Buffered…

如何簡單理解光圈大小對手機攝影的影響?

你&#xff0c;準備好參加今夏的朋友圈攝影大賽了嗎&#xff1f; 現在的天氣有多熱&#xff0c;誰出門誰知道&#xff01;出去玩還要背一臺單反&#xff0c;絕對可以說是一種折磨了。但是&#xff0c;如果你擁有一臺大光圈的手機&#xff0c;一樣可以在朋友圈脫穎而出。 那么…

基于centos6.7的docker私有倉庫搭建

2019獨角獸企業重金招聘Python工程師標準>>> 1 倉庫配置https認證 cd /etc/docker/ mkdir certs [rootdocker01 docker]# openssl req -newkey rsa:4096 -nodes -sha256 -keyout certs/docker01.key -x509 -days 365 -out certs/docker01.crt 填好相應的簡稱及email…

第十周軟件工程作業-每周例行報告

一、PSP T名稱C內容ST開始時間ED結束時間中斷時間/min實際時間/min會議第一次Scrum會議11月17日16:0011月17日16:30030第二次Scrum會議11月18日15:0011月18日15:30030第三次Scrum會議11月19日17:0011月19日17:30030第四次Scrum會議11月20日11:3511月20日12:15040第五次Scrum會議…

卷簾快門與全局快門的區別

https://wenku.baidu.com/view/2f0c8da0ce2f0066f5332283.html

MAVEN下載和安裝

1.maven的下載 下載鏈接http://maven.apache.org/download.cgi從該網站下載最新版本 2.maven的安裝 電腦上需要安裝JDK環境&#xff0c;需要安裝JDK7以上的版本。下載之后進行解壓&#xff0c;將maven解壓到不含中文和空格的一個目錄 maven目錄結構bin目錄&#xff1a;mvn.bat、…

洛谷 P3391 【模板】文藝平衡樹

題目背景 這是一道經典的Splay模板題——文藝平衡樹。 題目描述 您需要寫一種數據結構&#xff0c;來維護一個有序數列&#xff0c;其中需要提供以下操作&#xff1a;翻轉一個區間&#xff0c;例如原有序序列是5 4 3 2 1&#xff0c;翻轉區間是[2,4]的話&#xff0c;結果是5 2 …

CCD/CMOS靶面尺寸型號標準

傳感器尺寸指的是感光器對角線尺寸&#xff0c;1/1.7英寸&#xff08;14.8毫米&#xff0d;&#xff0d;導向管尺寸&#xff09;大于1/2.3英寸&#xff08;10.95毫米&#xff0d;&#xff0d;&#xff0d;導向管尺寸&#xff09;.采用同種技術水平的感光器&#xff0c;肯定是單…

分布式學習基礎知識

網絡通訊&#xff0c;網絡是分布式的基礎&#xff0c;對分布式的理解建立在對網絡的理解上&#xff0c;包括&#xff1a; OSI模型的7層TCP/IP&#xff0c;DNS&#xff0c;NATHTTP&#xff0c;SPDY/HTTP2Telnet網絡編程&#xff0c;是通過程序在多個主機之間通信。包括&#xff…

django中FastDFS客戶端與自定義文件存儲系統

什么是FastDFSFastDFS 是用 c 語言編寫的一款開源的分布式文件系統。FastDFS 為互聯網量身定制&#xff0c; 充分考慮了冗余備份、負載均衡、線性擴容等機制&#xff0c;并注重高可用、高性能等指標&#xff0c;使用 FastDFS 很容易搭建一套高性能的文件服務器集群提供文件上傳…

新近碰到的病毒(TR.Spy.Babonock.A)

先來段Microsoft的說明&#xff1a; Worm:Win32/Babonock.A Alert level: Severe Detected with Windows Defender Antivirus Also detected as:Worm/Win32.AutoIt (AhnLab)Trojan-Spy.Win32.AutoIt.p (Kaspersky)Worm/Autoit.ANVE (AVG)TR/Spy.Babonock.A (Avira)Win32/Autoit…