對於下圖使用dijkstra演算法求由頂點a到頂點h的最短路徑,按實驗報告模板編寫演算法。
第一點:
第二點:我們已經知道了起點s,一開始對於頂點s各個頂點的距離(用陣列dis[j]表示s->j的距離),我們可以通過與頂點s相連的邊得知。
假設頂點k,是距離頂點i最近的乙個頂點(除去s本身),頂點j是除去i,k以外的乙個節點
因此我們知道: dis[k] < dis[j]
再假設 dis[k] + path[k][j] < dis[j]
因此 如果我們先用頂點j去鬆弛其他邊是沒有意義的,因此dis[j]本身還是能夠被鬆弛,所以通過dis[j]鬆弛得到的最短邊並不是我們最優的解。
因此當dis[j]不能在被鬆弛的時候,說明此時dis[j]已經是s->j的最短距離,這是我們就可以用dis[j]來對其他邊進行鬆弛操作。
那到什麼時候dis[j]已經是最短了呢?
看回 dis[k] < dis[j]
可以推導出 dis[k] < dis[j] + path[j][k]
因此頂點j不能優化dis[k]
這裡就可以得出結論了,當dis[j]為剩下的頂點中距離i最近的頂點式,必定可以通過頂點j對其他邊進行鬆弛操作
void演算法**dijstra()
while (que.size()) //
通過維護小頂堆,優化了每次需要尋找vis[i] == 0 && dis[i] 最小的過程
}} }
}
時間複雜度:o(nlogn)
初始的dijstra演算法的時間複雜度是o(n^2),通過堆優化,可以logn的維護出邊權的最小值,不用再通過o(n)的遍歷來確定最小值。又因為有n個節點需要作為中轉點來對其他邊進行鬆弛操作,因此在堆優化之後dijstra演算法的時間複雜度就是o(nlogn)
空間複雜度:o(m + n)
通過鏈式前向星來維護邊的資訊,因此空間複雜度僅需要o(n + m)
#include#include完整**#include
#include
#include
using
namespace
std;
const
int maxn = 1e5 + 100
;const
int inf = 0x3f3f3f3f
;struct
node
node(
int x, int
y)
node() {}
};node edge[maxn];
//edge儲存邊的資訊
int head[maxn], cnt = 0
;void addedge(int u, int v, int val) //
通過鏈式前向星存圖能夠有效地降低空間複雜度
int n, m ,s; //
n 為頂點個數, m為邊數 , s是起點
priority_queueque; //
通過堆優化能夠有效地減少時間複雜度
int dis[maxn], vis[maxn]; //
dis維護從起點s到其他頂點地最段距離 , vis用來維護在進行演算法過程中那先頂點已經作為中轉點進行過鬆弛操作
void
dijstra()
while (que.size()) //
通過維護小頂堆,優化了每次需要尋找vis[i] == 0 && dis[i] 最小的過程}}
}int
main()
dijstra();
cout
<< "
頂點s到其他頂點的距離:
"<
for (int i = 1; i <= n; ++i)
return0;
}/*樣例輸入:
8 11
3 1 2
1 2 1
2 4 2
4 3 1
5 4 2
4 6 8
5 7 2
6 5 2
7 6 3
8 6 2
7 8 3
1*/
Dijstra演算法 C 實現
dijstra演算法思想,簡化版實現,從源節點開始調整,相鄰節點的最短距離。調整完之後,從距離最短並且沒有作為u的節點中選取下乙個節點 調整後面的節點,時間複雜度o v v e include define m 1000 using namespace std int map 5 5 int key...
最短路(Dijstra演算法)
一,問題基本概念 最短路問題 若網路中的每條邊都有乙個數值 長度,時間,成本等 則找出兩點 通常是源節點和阱節點 之間總權和最小的路徑就是最短路問題。單源最短路 可以採用dijkstra演算法 但是只可以求無負權的最短路徑 時間複雜度為o v 2 如果圖中又負權賄賂,可以採用bellman ford...
Dijstra演算法 單源最短路徑演算法
用dis陣列記錄起點到其餘所有點的最短路徑 include iostream include cstdio define inf 99999999 using namespace std int map 100 100 int dis 100 int book 100 book陣列記錄那些點已經被利...