單元最短路問題

2021-07-04 12:43:28 字數 2419 閱讀 6582

貪心策略,始終選擇從出發點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呢?...