Bellman-Ford演算法

來源:互聯網
上載者:User

 

 

Dijkstra演算法是處理單源最短路徑的有效演算法,但它局限於邊的權值非負的情況,若圖中出現權值為負的邊,Dijkstra演算法就會失效,求出的最短路徑就可能是錯的。這時候,就需要使用其他的演算法來求解最短路徑,Bellman-Ford演算法就是其中最常用的一個。該演算法由美國數學家理查德•貝爾曼(Richard Bellman, 動態規劃的提出者)和小萊斯特•福特(Lester Ford)發明。Bellman-Ford演算法的流程如下:
給定圖G(V, E)(其中V、E分別為圖G的頂點集與邊集),源點s,

·        數組Distant[i]記錄從源點s到頂點i的路徑長度,初始化數組Distant[n]為, Distant[s]為0;

·         
以下操作迴圈執行至多n-1次,n為頂點數:
對於每一條邊e(u, v),如果Distant[u] + w(u, v) < Distant[v],則另Distant[v] =Distant[u]+w(u, v)。w(u, v)為邊e(u,v)的權值;
若上述操作沒有對Distant進行更新,說明最短路徑已經尋找完畢,或者部分點不可達,跳出迴圈。否則執行下次迴圈;

·        為了檢測圖中是否存在負環路,即權值之和小於0的環路。對於每一條邊e(u, v),如果存在Distant[u] + w(u, v) < Distant[v]的邊,則圖中存在負環路,即是說改圖無法求出單源最短路徑。否則數組Distant[n]中記錄的就是源點s到各頂點的最短路徑長度。

可知,Bellman-Ford演算法尋找單源最短路徑的時間複雜度為O(V*E).

首先介紹一下鬆弛計算。如:

 


 

 

鬆弛計算之前,點B的值是8,但是點A的值加上邊上的權重2,得到5,比點B的值(8)小,所以,點B的值減小為5。這個過程的意義是,找到了一條通向B點更短的路線,且該路線是先經過點A,然後通過權重為2的邊,到達點B。
當然,如果出現一下情況


 

則不會修改點B的值,因為3+4>6。
 
Bellman-Ford演算法可以大致分為三個部分
第一,初始化所有點。每一個點儲存一個值,表示從原點到達這個點的距離,將原點的值設為0,其它的點的值設為無窮大(表示不可達)。
第二,進行迴圈,迴圈下標為從1到n-1(n等於圖中點的個數)。在迴圈內部,遍曆所有的邊,進行鬆弛計算。
第三,遍曆途中所有的邊(edge(u,v)),判斷是否存在這樣情況:
d(v) > d (u) + w(u,v)
則返回false,表示途中存在從源點可達的權為負的迴路。
 
之所以需要第三部分的原因,是因為,如果存在從源點可達的權為負的迴路。則應為無法收斂而導致不能求出最短路徑。
考慮如下的圖:
 

 

經過第一次遍曆後,點B的值變為5,點C的值變為8,這時,注意權重為-10的邊,這條邊的存在,導致點A的值變為-2。(8+ -10=-2)
 
 

第二次遍曆後,點B的值變為3,點C變為6,點A變為-4。正是因為有一條負邊在迴路中,導致每次遍曆後,各個點的值不斷變小。
 
在回過來看一下bellman-ford演算法的第三部分,遍曆所有邊,檢查是否存在d(v) > d (u) + w(u,v)。因為第二部分迴圈的次數是定長的,所以如果存在無法收斂的情況,則肯定能夠在第三部分中檢查出來。比如
 

 

此時,點A的值為-2,點B的值為5,邊AB的權重為5,5 > -2 + 5. 檢查出來這條邊沒有收斂。

 

所以,Bellman-Ford演算法可以解決圖中有權為負數的邊的單源最短路徑問。

 

poj3259

 

#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int N = 10010;const int INF = 999999;struct  Edge{    int u;    int v;    int t;} ;Edge edge[N];int num;int n,m,w;int dis[N] ;bool Bellman_ford(){    for(int i = 1; i <= n; i ++)    {        dis[i] = INF;    }    bool flag ;    for(int i = 1; i < n; i++)    {        flag = false;        for(int j = 1; j <= num; j++)        {            if(dis[edge[j].v] > dis[edge[j].u] + edge[j].t)            {                dis[ edge[j].v ] = dis[edge[j].u] + edge[j].t;                flag = true;            }        }        if( !flag )            break;    }    for(int j = 1; j <= num; j++)        if(dis[ edge[j].v ] > dis[edge[j].u] + edge[j].t)            return true;    return false;}int main(){    int F,a,b,c;    int tt;    cin >> F;    while(F--)    {        cin >> n >> m >> w;        num = 0;        memset(edge,0,sizeof(edge));        for(int i = 1; i <= m; i++)        {            cin >>a >> b >>c;            num ++;       //無向圖            edge[num].t = c;             edge[num].u = a;            edge[num].v = b;            num ++;            edge[num].t = c;            edge[num].u = b;            edge[num].v = a;        }        for(int i = 1; i <= w; i++)        {            cin >> a  >> b >> tt;            edge[++num].t = -tt;            edge[num].u = a;            edge[num].v = b;        }        if( Bellman_ford() )            cout << "YES\n";        else            cout << "NO"<<endl;    }    return 0;}

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.