標籤:檢查 pre 設定 ++ ++i 編寫 clu 比較 cstring
Bellman-Ford演算法是一種單源最短路演算法,允許圖中有負邊權。Bellman-Ford演算法的效率相對較低,但是很容易編寫,也很好理解。比較流行的SPFA演算法其實就是他的隊列最佳化。Bellman-Ford演算法的流程大體是這樣,先將源點的最短路設定為0,將其他結點的最短路設定為inf,然後進行n-1次迭代,每次檢查每條邊進行鬆弛操作,這樣就得到了其他結點的最短路。而且可以檢查是否存在負環,若n次迭代仍然可以進行鬆弛操作,則說明存在負環。不難看出時間複雜度是O(nm)的。怎麼理解Bellman-Ford演算法呢?不妨想想一棵最短路徑樹,根是源點,葉子結點是圖中其他結點,葉子結點到根節點的路徑就是其他結點的最短路。雖然這棵樹一開始我們並不知道什麼樣子,但他是客觀存在的。而Bellman-Ford演算法就是逐層構造這棵最短路樹,假設處理到了第i層,那麼第i-1層已經處理完畢,那麼掃描每一條邊,看是否可以鬆弛,一定可以由第i-1層擴充到第i層。如果把源點看做第0層,那麼這棵樹最多有n-1層,因此迭代n-1次一定可以得到這棵最短路樹(如果存在的話),那麼如果第n次仍然可以進行鬆弛操作,說明不存在最短路(存在負環)。
1 #include<cstdio> 2 #include<cctype> 3 #include<cstring> 4 const int inf=0x3f3f3f3f; 5 int n,m,s,d[maxn]; 6 struct edge { 7 int u,v,w; 8 edge(int u=0,int v=0,int w=-1):u(u),v(v),w(w) {} 9 } E[maxm];10 bool bellman() {11 memset(d,inf,sizeof(d));12 d[s]=0;13 for(int i=1;i<=n;++i) //迴圈檢查n次,正常情況下最多迭代n-1次,第n次用於判斷是否存在最短路14 for(int i=1;i<=m;++i) {15 int u=E[i].u,v=E[i].v,w=E[i].w;16 if(d[v]>d[u]+w) { //鬆弛操作17 if(i==n) return false;18 else d[v]=d[u]+w;19 }20 }21 return true;22 }23 int main() {24 scanf("%d%d%d",&n,&m,&s);25 int u,v,w;26 for(int i=1;i<=m;++i) {27 scanf("%d%d%d",&u,&v,&w);28 E[i]=edge(u,v,w);29 }30 if(!bellman()) printf("Wrong!");31 else for(int i=1;i<=n;++i) {32 if(i!=1) putchar(‘ ‘);33 printf("%d",d[i]);34 }35 return 0;36 }
Bellman-Ford演算法