bellman-ford的佇列優化
思想:每次僅對最短路程發生變化了的點的相鄰邊執行鬆弛操作。
如何知道當前哪些點的最短路程發生變化?此處可以用乙個佇列來維護這些點。
每次選取隊首頂點u,對頂點u的所有出邊進行鬆弛操作。例如有一條邊u→v的邊,如果通過u→v這條邊使得源點到頂點v的最短路徑變短(dis[u]+e[u][v]需要注意:同乙個頂點同時在佇列中出現多次是毫無意義的,所以我們需要乙個陣列來判重(判斷哪些點已經在佇列中)。在對頂點u的所有出邊鬆弛完畢後,就將頂點u出隊。接下來不斷從佇列中取出新的隊首頂點再進行如上操作,直至佇列空為止。
5 7
1 2 2
1 5 10
2 3 3
2 5 7
3 4 4
4 5 5
5 3 6
第一行2個整數n、m,n為頂點個數,m為邊的個數。接下來m行,每行3個數x、y、z,表示頂點x到頂點y的邊權值為z。
#include int main() ,book[6]=; //book陣列用來記錄哪些頂點已經在佇列中
int que[101]=,head=1,tail=1; //定義乙個佇列,並初始化佇列
int inf=99999999;
scanf("%d %d",&n,&m);
//初始化dis陣列,這裡是1號頂點到其餘各個頂點的初始路程
for(i=1;i<=n;i++)
dis[i]=inf;
dis[1]=0;
for(i=1;i<=n;i++) //初始化book陣列,初始化為0,剛開始都不在佇列中
book[i]=0;
for(i=1;i<=n;i++) //初始化first陣列下標1~n的值為-1,表示1~n頂點暫時都沒有邊
first[i]=-1;
for(i=1;i<=m;i++)
//1號頂點入隊
que[tail]=1;tail++;
book[1]=1; //標記1號頂點已經入隊
while(headdis[u[k]+wki]])
}k=next[k];
} book[que[head]]=0; //出隊
head++;
} for(i=1;i<=n;i++) //輸出1號頂點到其餘各個頂點的最短路徑
printf("%d ",dis[i]);
getchar();getchar();
return 0;
}
總結:初始時將源點加入佇列。每次從隊首head取出乙個頂點,並對與其相鄰的所有頂點進行鬆弛嘗試,若某個相鄰的頂點鬆弛成功,且這個相鄰的頂點不在佇列中(不在head~tail之間),則將它加入到佇列中。對當前頂點處理完畢後立即出隊,並對下乙個新隊首進行如上操作,直到隊列為空時演算法結束。此處用了乙個book來記錄每個頂點是否處在佇列中。也可以不要book陣列,檢查乙個頂點是否在佇列中,只需要把que[head]到que[tail]依次判斷一遍就可以,但這樣做的時間複雜度是o(n),而使用book陣列來記錄的話時間複雜度會降至o(1).
使用佇列優化的bellman-ford演算法的時間複雜度在最壞情況下也是o(nm)
。通過佇列優化的bellman-ford演算法如何判斷乙個圖是否有環?如果某個點進入佇列的次數超過n次,那麼這個圖肯定存在負環。
用佇列優化的bellman-ford演算法的關鍵之處在於:只有那些在前一遍鬆弛中改變了最短路程估計值的頂點,才可能引起它們鄰接點最短路程估計值發生改變。因此,用乙個佇列來存放被成功鬆弛的頂點,之後只對佇列中的點進行處理,這就降低了演算法的時間複雜度。
最短路徑演算法分析
floyd
dijkstra
bellman-foed
佇列優化的bellman-ford
空間複雜度
o(n*n)
o(m)
o(m)
o(m)
時間複雜度
o(n*n*n)
o((m+n)logn)
o(mn)
最壞o(mn)
適用情況
稠密圖(和頂點關係密切)
稠密圖(和頂點關係密切)
稀疏圖(與邊關係密切)
稀疏圖(與邊關係密切)
負權可以解決
不能解決
可以解決
可以解決
Bellman Ford演算法的佇列優化
dijkstra演算法求最短路徑的圖時不能有負權邊,因為擴充套件到負權邊的時候會產生更短的路徑,有可就已經破壞了已經更新的點路程不會改變的性質。dijkstra演算法雖然好,具有良好的擴充套件性,擴充套件後可以適應很多問題,高效的a 演算法就是有dijkstra演算法擴充套件來的,但dijkstra...
SPFA 佇列優化的Bellman Ford演算法
spfa shortest path faster algorithm 演算法思想基於bellman ford演算法 進行優化的方式是 在進行某一次鬆弛操作中 如果起點到乙個點的距離不變 那麼以這個點為中轉點能到達的點距起點的距離不變 如果這個點的距離發生了變化 就將這個點入佇列 以求通過這個點中轉...
Bellman Ford演算法 佇列優化
如果說dijistra演算法是通過點來對各個路徑進行鬆弛的話,那麼bellman ford是演算法則是通過邊來對進行鬆弛的。即列舉每一條邊,然後比較源點到該邊的終點的估計最短路徑估計值和源點到該邊的起點的最短路徑估計值加上該邊的長度,例如,已知源點到各個點的最短路徑估計值dis i 為 0 5 2 ...