三種最短路的總結

2021-09-26 07:12:35 字數 1571 閱讀 6114

三種最短路演算法的對比

floyd 

dijkstra

bellman-ford

空間複雜度

o(n^2)

0(m)

0(m)

時間嗎複雜度

o(n3)    

o((m+n)logn)  

o(mn)

適用情況

稠密圖稠密圖

稀疏圖負權邊

不可以不可以

可以floyd演算法簡單,dijkstra不能解決負權邊優化後可以得到mlogn的複雜度,bellman可以解決負權邊。

下面再介紹一下貝爾曼、福特演算法的優化

給定的圖存在負權邊,這時類似dijkstra等演算法便沒有了用武之地,而bellman-ford演算法的複雜度又過高,spfa演算法便派上用場了。 我們約定有向加權圖g不存在負權迴路,即最短路徑一定存在。當然,我們可以在執行該演算法前做一次拓撲排序,以判斷是否存在負權迴路,但這不是我們討論的重點。

演算法思想:我們用陣列d記錄每個結點的最短路徑估計值,用鄰接表來儲存圖g。我們採取的方法是動態逼近法:設立乙個先進先出的佇列用來儲存待優化的結點,優化時每次取出隊首結點u,並且用u點當前的最短路徑估計值對離開u點所指向的結點v進行鬆弛操作,如果v點的最短路徑估計值有所調整,且v點不在當前的佇列中,就將v點放入隊尾。這樣不斷從佇列中取出結點來進行鬆弛操作,直至佇列空為止

期望的時間複雜度o(k e), 其中k為所有頂點進隊的平均次數,可以證明k一般小於等於2。

實現方法:

建立乙個佇列,初始時佇列裡只有起始點,再建立乙個**記錄起始點到所有點的最短路徑(該**的初始值要賦為極大值,該點到他本身的路徑賦為0)。然後執行鬆弛操作,用佇列裡有的點作為起始點去重新整理到所有點的最短路,如果重新整理成功且被重新整理點不在佇列中則把該點加入到佇列最後。重複執行直到隊列為空。

判斷有無負環:

如果某個點進入佇列的次數超過n次則存在負環(spfa無法處理帶負環的圖)

暫時先給出**,具體我也沒理解清楚;

#include#include#include#define n 210

#define m 2010

#define inf 0x3f3f3f3f//定義無窮大

using namespace std;

int dis[n],vis[n],head[n],n,m,edgenum;

struct nodeedge[m];

void init()

void add(int u,int v,int w);

edge[edgenum]=e;

head[u]=edgenum++;

}void spfa(int beg,int end)

}} }

if(dis[end]==inf)

printf("-1\n");

else

printf("%d\n",dis[end]);

}int main()

int beg,end;

scanf("%d%d",&beg,&end);

spfa(beg,end);

} return 0;

}

最短路徑是三種求法

說是總結,其實自己也沒有學多長時間只是把自己這段時間的一些經驗總結下來,用來供後來的初學者漲點經驗吧。對於學習演算法,個人的理解就是首先要去理解演算法的本質,然後想想演算法的實現過程,如何用 去描述這個演算法,然後就是去記模板了 對於像我這種初學者來說,這一步其實蠻重要的 另外說下做最短路問題的一些...

最短路徑的三種實現方法

helpbuptguoan created by new life on 16 8 24.include include include include include include include using namespace std define n 5 圖的大小 const int typ...

三種最短路並鄰接表的模板

struct node sa maxn 5 void push int x,int y,int z void floyd int n for int j 1 j n j if s i k s k j s i j void floyd empty int n else void dijkstra in...