时间复杂度对比:
Dijkstra:
O
(
n
2
)
O(n^2)
O(n2)
Dijkstra + 优先队列(堆优化):
O
(
2
∗
E
+
V
∗
l
o
g
V
)
O(2*E+V*logV)
O(2∗E+V∗logV)
SPFA:
O
(
k
∗
E
)
O(k*E)
O(k∗E),
k
k
k为每个节点进入队列的次数,一般小于等于
2
2
2,最坏情况为
O
(
V
∗
E
)
O(V*E)
O(V∗E)
BellmanFord:
O
(
V
∗
E
)
O(V*E)
O(V∗E),可检测负圈
Floyd:
O
(
n
3
)
O(n^3)
O(n3),计算每对节点之间的最短路径
结论:
①
①
①当权值为非负时,用Dijkstra。
②
②
②当权值有负值,且没有负圈,则用SPFA,SPFA能检测负圈,但是不能输出负圈。
③
③
③当权值有负值,而且可能存在负圈,则用BellmanFord,能够检测并输出负圈。
④
④
④SPFA检测负环:当存在一个点入队大于等于V次时,则有负环。
P S PS PS:优先队列和SPFA都有可能被题目卡数据 . . . . . . ...... ......
Floyd:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = INT_MAX/100;
int n, m, d[3000][3000];
void floyed() {
for(int k=0; k<n; k++) { //插入k点
for(int i=0; i<n; i++) {
for(int j=0; j<n; j++) {
if(d[i][k]<INF && d[k][j]<INF) //消除加法溢出问题
d[i][j]=min(d[i][j], d[i][k]+d[k][j]); //更新两点距离
}
}
}
}
void init() {
scanf("%d%d", &n, &m);
for(int i=0; i<n; i++) {
for(int j=0; j<n; j++)
if(i==j) d[i][j]=0;
else d[i][j]=INF;
}
for(int i=0; i<m; i++) {
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
d[x-1][y-1]=z;
}
}
int main() {
init();
floyed();
}