1. 程式人生 > >Bellman-Ford算法

Bellman-Ford算法

ctype 操作 復雜 時間 wro sca 判斷 == scan

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算法