最短路基礎演算法

2021-10-07 16:30:15 字數 3721 閱讀 3597

最短路基礎演算法:dijkstra,spfa,floyd,bellman-ford

dijkstra一般情況慢於spfa,但特殊情況下spfa會被卡,而dijkstra不會.該演算法不能處理負權邊.

spfa編寫難度小於dijkstra,且可處理負權邊

luogu p3371 【模板】單源最短路徑(弱化版)

luogu p4779 【模板】單源最短路徑(標準版)(卡spfa)

1.dijkstra

使用dis[ ]陣列存放該點到起始點的最短距離,每次尋找所有dis[ ]中最小的節點,並以該節點更新其他節點,複雜度o(n2).尋找最小節點可使用堆優化,優化時間複雜度至o(nlogn).

不使用堆優化:

//dijkstra

#include

using

namespace std;

struct edge

;listnode[

10005];

int dis[

10005];

int vis[

10005];

int n,m,s,x,y,z;

intmain()

for(

int i=

1;i<=m;i++))

;}dis[s]=0

; queue<

int>q;

q.push

(s);

while

(!q.

empty()

)}for(

int i=

1;i<=n;i++)}

if(minid!=-1

)}for(

int i=

1;i<=n;i++

)return0;

}

使用堆優化:

//dijkstra,堆優化

#include

#define maxn 10005

#define inf 2147483647

using

namespace std;

struct dijkstra

;struct int

};priority_queueq;

listnode[maxn]

;int dis[maxn]

;int vis[maxn]

;void

init

(int n)

}void

add(

int u,

int v,

int w));

}void

dijkstra

(int s));

while

(!q.

empty()

));}

}}}}

;int n,m,s,x,y,z;

dijkstra a;

intmain()

a.dijkstra

(s);

for(

int i=

1;i<=n;i++

)return0;

}

2.spfa

無負權值時不要作死用spfa,多半會被卡

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

判斷有無負環:

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

最差情況時間複雜度:o(nm)

//spfa

#include

#define inf 2147483648-1

#define maxn 10005

using

namespace std;

struct spfa

; vectornode[maxn]

;int inq[maxn]

,inq_cnt[maxn]

;int dis[maxn]

;int n;

void

init

(int n)

this

->n=n;

}void

add(

int x,

int y,

int v));

}int

spfa

(int s)

//有負環,不能找到最短路

for(

auto

& i:node[now])}

}}return1;

//能找到最短路}}

;int n,m,s,x,y,z;

spfa spfa;

intmain()

spfa.

spfa

(s);

for(

int i=

1;i<=n;i++

)return0;

}

3.floyd

可求任意兩點的最短路,可處理負權邊,複雜度o(n3).模板

for

(int k=

1;k<=n;k++)}

}

4.bellman-ford

思路:1.初始化時將起點s到各個頂點v的距離dist(s->v)賦值為∞,dist(s->s)賦值為0;

2.後續進行最多n-1次遍歷操作(n為頂點個數),對所有的邊進行鬆弛操作;

所謂的鬆弛,以邊ab為例,若dist(a)代表起點s到達a點所需要花費的總數,

dist(b)代表起點s到達b點所需要花費的總數,weight(ab)代表邊ab的權重,

若存在:

(dist(a) +weight(ab)) < dist(b)

則說明存在到b的更短的路徑,s->...->a->b,更新b點的總花費為(dist(a) +weight(ab)),父節點為a

3.遍歷都結束後,若再進行一次遍歷,還能得到s到某些節點更短的路徑的話,則說明存在負環路。

這個演算法太慢了,spfa最差情況和它速度一樣,可能判斷負環會比spfa快一些。判斷負環就完成迴圈以後再找一次,若還能更新,則有負環。

//bellman-ford

#include

using

namespace std;

struct edge

;vectoredge;

long

long dis[

10005];

int n,m,s,u,v,w;

intmain()

for(

int i=

1;i<=m;i++))

;}dis[s]=0

;for

(int i=

1;i<=n-

1;i++)}

}for

(int i=

1;i<=n;i++

)return0;

}

HDU 2544 (最短路基礎題模板題)

problem description 在每年的校賽裡,所有進入決賽的同學都會獲得一件很漂亮的t shirt。但是每當我們的工作人員把上百件的衣服從商店運回到賽場的時候,卻是非常累的!所以現在他們想要尋找最短的從商店到賽場的路線,你可以幫助他們嗎?input 輸入包括多組資料。每組資料第一行是兩個整...

最短路徑演算法 最短路

在每年的校賽裡,所有進入決賽的同學都會獲得一件很漂亮的t shirt。但是每當我們的工作人員把上百件的衣服從商店運回到賽場的時候,卻是非常累的!所以現在他們想要尋找最短的從商店到賽場的路線,你可以幫助他們嗎?input 輸入包括多組資料。每組資料第一行是兩個整數n m n 100,m 10000 n...

基礎最短路

description 在每年的校賽裡,所有進入決賽的同學都會獲得一件很漂亮的t shirt。但是每當我們的工作人員把 上百件的衣服從商店運回到賽場的時候,卻是非常累的!所以現在他們想要尋找最短的從商店到賽場 的路線,你可以幫助他們嗎?input 輸入包括多組資料。每組資料第一行是兩個整數n m n...