如果說dijistra演算法是通過點來對各個路徑進行鬆弛的話,那麼bellman-ford是演算法則是通過邊來對進行鬆弛的。
即列舉每一條邊,然後比較源點到該邊的終點的估計最短路徑估計值和源點到該邊的起點的最短路徑估計值加上該邊的長度,
例如,已知源點到各個點的最短路徑估計值dis[i]為 0 5 2 6 7,有一條邊的資訊為從點3到點4的長度為3,那麼此時通過改變來進行鬆弛可以將dis[4] = 6鬆弛為2+3=5了,是不是感覺有些眉目了。 所以
for(j = 1; j <= m; ++j)
if(dis[v[j]] > dis[u[j]]+w[j])
dis[v[j]] = dis[u[j]]+w[j];
此時我們可以將鬆弛x輪的過程理解為最多通過x條邊可以獲得最短路徑。
所以乙個圖中最多只能通過n-1條邊獲得最短路徑
下面上**,
#include #include #define inf 10e7
using namespace std;
int u[105], v[105], w[105], dis[105], jk[105];
int main()
for(i = 1; i <= n; ++i)
printf("%d ", dis[i]);
printf("\n");
} return 0;
}
時間複雜度為o(mn),時間複雜度相比dijistra演算法似乎有些高,但實際上,bellman-ford演算法經常會在未達到n-1輪就已經計算出最短路徑了,所以還可以優化,所以博主是很喜歡這個演算法的。
#include #include #define inf 10e7
using namespace std;
int u[105], v[105], w[105], dis[105], jk[105];
int main()
} for(i = 1; i <= n; ++i)
printf("%d ", dis[i]);
printf("\n");
} return 0;
}
在這兒我們可以體會到,在每次完成一輪鬆弛之後,便會有一些點已經求得最短路徑,一會這些最短路徑估計值便不會改變,不再受後面鬆弛的影響,但以後每次還是要判斷是否鬆弛,浪費了時間。所以,每次僅對最短路徑發生變化了的頂點的所有出邊進行鬆弛操作。這就引出了我們的佇列優化的bellman-ford演算法,又叫做spfa演算法。
#include using namespace std;
const int inf = 0x3f3f3f3f;
struct node1edge[20005];
int n, m, no, head[105], dis[105], book[105], pre[105];
queueq;
void add(int u, int v, int w)
void init()
void spfa(int u)
} k = edge[k].next;
} }
} void printpath(int end)
cout << endl;
}int main()
spfa(1);
for(i = 1; i <= n; ++i) printf("%d ", dis[i]);
printf("\n");
printpath(5);
} return 0; }/*
樣例:5 5
1 2 2
1 3 3
2 4 4
3 4 2
4 5 1
*/
已經介紹完所有最短路徑的演算法了,如果對floyed-warshell演算法和dijistra演算法有興趣的朋友可以看前兩篇文章。
Bellman Ford演算法的佇列優化
dijkstra演算法求最短路徑的圖時不能有負權邊,因為擴充套件到負權邊的時候會產生更短的路徑,有可就已經破壞了已經更新的點路程不會改變的性質。dijkstra演算法雖然好,具有良好的擴充套件性,擴充套件後可以適應很多問題,高效的a 演算法就是有dijkstra演算法擴充套件來的,但dijkstra...
Bellman Ford演算法及其佇列優化與實戰入門
bellman ford演算法能解決負權邊的圖,就是說能夠來判斷存在負環。先來看一下核心 dis i 為源點到i點的最短路 for k 1 k n 1 k n為頂點的個數 for int i 1 i m i m為邊的條數 if dis v i dis u i w i u i 為第i條邊的起點,v i...
六 Bellman Ford演算法的佇列優化
由於bellman ford演算法在每實施一次鬆弛操作後,就會有一些頂點已經求得其最短路,此後這些頂點的最短路的估計值就一直保持不變,不再受到後續鬆弛操作的影響,但是每次還要判斷是否需要鬆弛,浪費了時間 優化方法 每次僅對最短路估計值發生改變了的頂點的所有出邊進行鬆弛操作 求圖中1號頂點到2 3 4...