貪心策略,始終選擇從出發點s到達頂點i的當前最短距離為d[i].那麼就會出現下列推導關係:
d[i]=min(其中cost(j,i)表示從頂點j到頂點i的權值)
如果給定的圖是dag,那麼就可以按拓撲序給頂點編號,並且利用上述推到關係計算,但是如果給定圖
中有圈,就無法依照這樣的順序來進行計算。在這種情況下,記到達當前頂點i的距離是d[i],
並設初值d[s]=0,d[i]=inf(足夠大的常數),再不斷使用該遞推關係更新d[i],只要途中不存在負圈
更新就是有限的。
//從頂點from指向頂點to的權值為cost的邊
struct edge;
edge es[max+e]; //邊
int d[max_v]; //從源點到頂點i的距離
int v,e; //v頂點數,e邊數
//求解從頂點s出發到達所有頂點的最短距離
void bellman_ford(int s)
}//存在負圈
if(!flag)
break;
}}
如果圖中不存在負圈,那麼最短路徑不會經過同乙個頂點兩次(也就是說,最多通過|v|-1條邊)
外層迴圈最多執行|v|-1次。因此時間複雜度為o(|v|*|e|).如果存在負圈,那麼在第|v|次迴圈中也會
更新d,因此可以用該性質檢查負圈。如果從一開始對所有的頂點i,都把d[i]初始化為0,那麼就可以檢查
所有的負圈。
// 返回值為true,表明存在負圈
bool find_negative_loop()
//如果第n次更新了,就說明存則負圈
if(i==v-1)
return
true; }}
return
false;
}
dijkstra演算法處理的情況是bellman-ford演算法處理情況的乙個特例,也就是沒有負邊的情況。
在bellman_ford演算法中,如果d[i]還不是最短距離的話,那麼即使進行d[j]=d[i]+cost(i,j)的更新,
的d[j]也不會變成最短距離。同時,即使d[i]沒有任何變化,每次迴圈也要檢查一遍從i出發的所有邊
而dijkstra演算法對此作出了改進:
(1)找到最短距離已經確定的頂點,從它出發更新相鄰頂點的最短距離
(2)此後不需要關注(1)中的最短距離已經確定的頂點。
此處最重要的就是如何確定最短距離已經確定的頂點。在初始化時,只有起點的最短距離是確定的。
而在尚未使用的頂點中,距離d[i]最小的頂點的最短距離已經確定。
//cost[u][v]表示邊e=(u,v)的權值,不存在inf
int cost[max_v][max_v];
//從頂點s出發到達各個頂點的最短距離
int d[max_v];
//已經使用過的頂點
bool used[max_v];
//頂點數
int v;
//從頂點s出發到各個頂點的最短距離
void dijkstra(int s)
used[s]=true;
while(true)
} /*
*以上for迴圈結束以後會產生兩種結果:v==-1或者v!=-1
* 當v==-1:表明每乙個頂點都已經用過,此時應該退出
* 或者是d[i] 0<=iif(v==-1)
break;
used[v]=true;
//更新從當下頂點到各個頂點的最短距離
for(int i=0;imin(d[i],d[v]+cost[v][i]);} }
}
使用鄰接矩陣實現dijtstra演算法的複雜度是o(|v|2)。同樣會使用鄰接表時間複雜度也是一樣。
時間的耗費主要是數值的更新以及取出最小值兩個操作。因此使用堆來進行操作。把每個頂點當前的
最短距離用堆維護,在更新最短距離時,把對應元素向根的方向移動以滿足堆的性質。每次從堆內部取
出的最小值就是下一次要使用的頂點。這樣堆中共有元素o(|v|)個,共進行o(|e|)次操作,因此該演算法
的複雜度為o(|e|log|v|)
struct edge;
typedef pair p; //first是最短距離,second是頂點的 編號
int v; // 頂點的數目
vector
g[max_v]; //圖
int d[max_v]; //從頂點s出發到達各個頂點的最短距離
void dijkstra2(int s)} }
}
單元最短路徑問題
給定乙個帶權有向圖 g v,e 其中每條邊的權是乙個非負實數。另外,還給定 v 中的乙個頂點,稱為源。現在我們要計算從源到所有其他各頂點的最短路徑長度。這裡的長度是指路上各邊權之和。這個問題通常稱為單源最短路徑問題。dijkstra演算法 public class dijkstra dijkstra...
單元最短路
在乙個有 n 個點,m 個邊的有向圖中,已知每條邊長,求出 1 到 n 的最短路徑,返回 1 到 n 的最短路徑值。如果 1 無法到 n 輸出 1 圖中可能有重邊,無自環。import j a.util.public class solution for int i 0 i graph.length...
談談單元最短路
單元最短路,應該會立即想到spfa和dijkstra。相較而言,我用spfa的次數更加多一些,一般這些題目都可以用 spfa 演算法 資料結構 邊表給做掉,借用了 這位大神的 我們一般用的都是spfa的bfs應用,這是比較正確的,一般情況下 bfs演算法優勢明顯,但是為什麼還需要dijkstra呢?...