1. 程式人生 > >bellman-ford演算法——最短路問題,判斷是否存在負權迴路或正權迴路

bellman-ford演算法——最短路問題,判斷是否存在負權迴路或正權迴路

Dijkstra演算法是處理單源最短路徑的有效演算法,但它侷限於邊的權值非負的情況,若圖中出現權值為負的邊,Dijkstra演算法就會失效,求出的最短路徑就可能是錯的。

這時候,就需要使用其他的演算法來求解最短路徑,Bellman-Ford演算法就是其中最常用的一個。該演算法由美國數學家理查德貝爾曼(Richard Bellman, 動態規劃的提出者)和小萊斯特福特(Lester Ford)發明。

適用條件&範圍:

單源最短路徑(從源點s到其它所有頂點v);

有向圖&無向圖(無向圖可以看作(u,v),(v,u)同屬於邊集E的有向圖);

邊權可正可負(如有負權迴路輸出錯誤提示

);

差分約束系統;

Bellman-Ford演算法的流程如下:
給定圖G(V, E)(其中VE分別為圖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).

BellmanFord演算法可以大致分為三個部分
第一,初始化所有點。每一個點儲存一個值,表示從原點到達這個點的距離,將原點的值設為0,其它的點的值設為無窮大(表示不可達)。
第二,進行迴圈,迴圈下標為從1n1n等於圖中點的個數)。在迴圈內部,遍歷所有的邊,進行鬆弛計算。


第三,遍歷途中所有的邊(edgeuv)),判斷是否存在這樣情況:
dv) > d (u) + w(u,v)
則返回false,表示途中存在從源點可達的權為負的迴路。
 
之所以需要第三部分的原因,是因為,如果存在從源點可達的權為負的迴路。則 應為無法收斂而導致不能求出最短路徑。 

測試程式碼如下:(下面為有向圖的Bellman-Ford演算法。。。。。)
PS:很簡單的演算法,沒什麼特別好說的。自己的程式碼

#include<bits/stdc++.h>
using namespace std;
#define maxn 999
#define inf 0x3f3f3f3f
typedef struct Edge{int form;int to;int w;}edge;
edge ma[maxn];
int dis[maxn];
int k,node,v;
int bellman_ford()
{
    for(int i=1;i<=node;i++) //初始化,找正權迴路是初始化為0
        dis[i]=inf; //dis代表著從源點到i的距離
    dis[v]=0;
    for(int i=1;i<=node-1;i++)   //歷遍每一個點
    {
        for(int j=1;j<=k;j++) //歷遍每條邊
        {
            if(dis[ma[j].form]>dis[ma[j].to]+ma[j].w) //如果v-form的距離大於v-to+to-from的距離就更新v-form的距離
            {
                dis[ma[j].form]=dis[ma[j].to]+ma[j].w;
            }
        }
    }
    int flag=1;
    for(int i=1;i<=k;i++)  //判斷是否有負權迴路,改變條件後也可以判斷是否有正權迴路
    {
        if(dis[ma[i].form]>dis[ma[i].to]+ma[i].w)
        {
            flag=0;
            break;
        }
    }
    return flag;
}
int main()
{
    scanf("%d %d %d",&node,&k,&v);
    for(int i=1;i<=k;i++)
    {
        scanf("%d%d%d",&ma[i].form,&ma[i].to,&ma[i].w);
    }
    if(bellman_ford())
    {
        for(int i=1;i<=node;i++)
        {
            printf("%d\n",dis[i]);
        }
    }
    else
        printf("have negative circle\n");
}


相關推薦

bellman-ford演算法——短路問題判斷是否存在迴路迴路

Dijkstra演算法是處理單源最短路徑的有效演算法,但它侷限於邊的權值非負的情況,若圖中出現權值為負的邊,Dijkstra演算法就會失效,求出的最短路徑就可能是錯的。 這時候,就需要使用其他的演算法來求解最短路徑,Bellman-Ford演算法就是其中最常用的一個

bellman-ford演算法 短路

重要應用:在負權的圖的單源最短路問題 Bellman-Ford 演算法和 Dijkstra 演算法都是可以解決單源最短路徑的演算法,一個實現的很好的 Dijkstra 演算法比 Bellman-Ford 演算法的執行時間要低,但dijkstra演算法無法解決存

[ACM] hdu 1217 Arbitrage (bellman_ford短路判斷是否有迴路Floyed)

Arbitrage Problem Description Arbitrage is the use of discrepancies in currency exchange rates to transform one unit of a currency in

單源短路——(Bellman-Ford演算法)超詳細

今天看了一下午的白書的Bellman-Ford演算法,由於能力有限,可能理解不到位。。。。 感覺就是遍歷所有邊更新點,如果有更新的點,繼續遍歷所有邊,直到沒有點更新就退出. #include <iostream> #include <stdio.h> #inc

短路Bellman-ford演算法

今天看啊哈演算法搞懂了Bellman-ford演算法,其實核心程式碼只有四行,還是蠻簡單的,寫了一個板子,程式碼分析容後再議 (我才不是想水部落格呢……) #include <iostream

ACM:短路dijkstra鄰接表的建立使用鄰接表跟優先佇列的dijkstraBellman-FordFloyd。。

(一)dijkstra,鄰接矩陣 所有邊權均為正,不管有沒有環,求單個源點出發,到所有節點的最短路。該方法同時適用於有向圖和無向圖。 #include <iostream> #include <string> #include <stack&g

帶有值的單源短路徑-bellman-ford演算法

https://baike.baidu.com/item/Bellman-Ford%E7%AE%97%E6%B3%95/1089090?fr=aladdin&fromid=6039406&fromtitle=bellman-ford 參考百科的c++實現版本 import java.

紫書第十一章-----圖論模型與演算法短路徑Dijkstra演算法Bellman-Ford演算法Floyd演算法

最短路徑演算法一之Dijkstra演算法 演算法描述:在無向圖 G=(V,E) 中,假設每條邊 E[i] 的長度為 w[i],找到由頂點 V0 到其餘各點的最短路徑。 使用條件:單源最短路徑,適用於邊權非負的情況 結合上圖具體搜尋過程,我繪出下表,方便

Bellman-Ford演算法和佇列優化(SPFA)——求單源短路徑

來源自我的部落格 #include <stdio.h> #include <limits.h> int main(){ int n, m; scanf("%

單源短路徑之Bellman-Ford演算法

今天介紹一種計算單源最短路徑的演算法Bellman-Ford演算法,對於圖G=(V,E)來說,該演算法的時間複雜度為O(VE),其中V是頂點數,E是邊數。Bellman-Ford演算法適用於任何有向圖,並能報告圖中存在負環路(邊的權重之和為負數的環路,這使得圖中所有經過該環

短路徑問題:貝文曼福德(Bellman Ford)演算法 & Java 實現

一、貝爾曼福德演算法 1. 簡介 貝爾曼福德(Bellman Ford)演算法也是求解單源最短路徑問題,相比狄克斯特拉(dijkstra)演算法,它執行效率會差一些,但是它可以處理邊的權重為負值的情況,而狄克斯特拉演算法要求變的權重不能為負數。 2. 演算法思

小費用流bellman-ford演算法總結

最小費用流問題是尋找流為F時的最小費用,普通的最大流中邊只有流量限制,而在費用流中還加上了費用,為保證過程可逆和正確性殘餘網路中的負權邊是原邊費用的相反數,求解此類問題的方法依然是貪心,我們在殘餘網路上總是沿著最短路增廣,這樣可以保證在當前流量下,取得最小的費用(權值為費用

Bellman-Ford演算法—求解帶邊的短路徑

1.Dijkstra不能得到含有負權邊圖(這裡就不是環路了)的單源最短路徑 Dijkstra由於是貪心的,每次都找一個距源點最近的點(dmin),然後將該距離定為這個點到源點的最短路徑(d[i]<--dmin);但如果存在負權邊,那就有可能先通過並不是距源點最近的一個

圖論演算法----短路徑Bellman-Ford演算法詳解

一、題目描述 最短路徑問題 題目描述 平面上有n個點(n<=100),每個點的座標均在-10000~10000之間。其中的一些點之間有連線。若有連線,則表示可從一個點到達另一個點,即兩點間有

練習題 No.22 判斷是否有圈(Bellman-Ford演算法

要求 給出一個有向圖,讓你求這個圈裡是否有負權環 限制條件 無 輸入格式 第一行輸入V,E分別代表頂點數和邊數 接下來E行,每行輸入from to cost 代表從from到to的距離為

演算法:2、計算帶有值的單源短路徑:Bellman-Ford演算法

原文地址:http://www.wutianqi.com/?p=1912 相關文章: 1.Dijkstra演算法: 2.Floyd演算法: Dijkstra演算法是處理單源最短路徑的有效演算法,但它侷限於邊的權值非負的情況,若圖中出現權值為負的邊,Dijkst

POJ 2253 Frogger poj3660Cow Contest(判斷絕對順序)(短路floyed)

技術 memset lse 關系 size using onclick second win POJ 2253 Frogger題目意思就是求所有路徑中最大路徑中的最小值。 #include<iostream> #include<cstdio&g

HDOJ 1217 Arbitrage(擬短路floyd算法)

same double script strong ram tar per bre center Arbitrage Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/

短路dijstra算法

ear 代碼 大於 鏈表 include n) clear esp als #include<iostream> #include<stdio.h> #include<math.h> #include<vector> usi

POJ 3259 Wormholes【短路/SPFA判斷環模板】

改變 air ont 數組 算法 他會 HERE push_back init 農夫約翰在探索他的許多農場,發現了一些驚人的蟲洞。蟲洞是很奇特的,因為它是一個單向通道,可讓你進入蟲洞的前達到目的地!他的N(1≤N≤500)個農場被編號為1..N,之間有M(1&l