• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆 - 70  文章 - 160  trackbacks - 0

            公告:
            知識共享許可協(xié)議
            本博客采用知識共享署名 2.5 中國大陸許可協(xié)議進行許可。本博客版權(quán)歸作者所有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意不得隨機刪除文章任何內(nèi)容,且在文章頁面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。 具體操作方式可參考此處。如您有任何疑問或者授權(quán)方面的協(xié)商,請給我留言。

            常用鏈接

            留言簿(8)

            隨筆檔案

            文章檔案

            搜索

            •  

            積分與排名

            • 積分 - 179360
            • 排名 - 147

            最新評論

            閱讀排行榜

            評論排行榜

            相關(guān)文章:

            1.Dijkstra算法:

            http://www.wutianqi.com/?p=1890

            2.Floyd算法:

            http://www.wutianqi.com/?p=1903

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

            • 數(shù)組Distant[i]記錄從源點s到頂點i的路徑長度,初始化數(shù)組Distant[n]為, Distant[s]為0;
            •  
              以下操作循環(huán)執(zhí)行至多n-1次,n為頂點數(shù):
              對于每一條邊e(u, v),如果Distant[u] + w(u, v) < Distant[v],則另Distant[v] = Distant[u]+w(u, v)。w(u, v)為邊e(u,v)的權(quán)值;
              若上述操作沒有對Distant進行更新,說明最短路徑已經(jīng)查找完畢,或者部分點不可達,跳出循環(huán)。否則執(zhí)行下次循環(huán);
            • 為了檢測圖中是否存在負環(huán)路,即權(quán)值之和小于0的環(huán)路。對于每一條邊e(u, v),如果存在Distant[u] + w(u, v) < Distant[v]的邊,則圖中存在負環(huán)路,即是說改圖無法求出單源最短路徑。否則數(shù)組Distant[n]中記錄的就是源點s到各頂點的最短路徑長度。

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

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


             

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


             

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

            經(jīng)過第一次遍歷后,點B的值變?yōu)?,點C的值變?yōu)?,這時,注意權(quán)重為-10的邊,這條邊的存在,導(dǎo)致點A的值變?yōu)椋?。(8+ -10=-2)
             
             

            第二次遍歷后,點B的值變?yōu)?,點C變?yōu)?,點A變?yōu)椋?。正是因為有一條負邊在回路中,導(dǎo)致每次遍歷后,各個點的值不斷變小。
             
            在回過來看一下bellman-ford算法的第三部分,遍歷所有邊,檢查是否存在d(v) > d (u) + w(u,v)。因為第二部分循環(huán)的次數(shù)是定長的,所以如果存在無法收斂的情況,則肯定能夠在第三部分中檢查出來。比如
             

            此時,點A的值為-2,點B的值為5,邊AB的權(quán)重為5,5 > -2 + 5. 檢查出來這條邊沒有收斂。
             
            所以,Bellman-Ford算法可以解決圖中有權(quán)為負數(shù)的邊的單源最短路徑問。

            個人感覺算法導(dǎo)論講解很不錯,把這一章貼出來和大家分享:

            24.1 The Bellman-Ford algorithm

            The Bellman-Ford algorithm solves the single-source shortest-paths problem in the general case in which edge weights may be negative. Given a weighted, directed graph G = (V, E) with source s and weight function w : E  R, the Bellman-Ford algorithm returns a boolean value indicating whether or not there is a negative-weight cycle that is reachable from the source. If there is such a cycle, the algorithm indicates that no solution exists. If there is no such cycle, the algorithm produces the shortest paths and their weights.

            The algorithm uses relaxation, progressively decreasing an estimate d[v] on the weight of a shortest path from the source s to each vertex v  V until it achieves the actual shortest-path weight δ(s, v). The algorithm returns TRUE if and only if the graph contains no negative-weight cycles that are reachable from the source.

            BELLMAN-FORD(G, w, s)
            1  INITIALIZE-SINGLE-SOURCE(G, s)
            2  for i1 to |V[G]| - 1
            3       do for each edge (u, v) ∈ E[G]
            4              do RELAX(u, v, w)
            5  for each edge (u, v) ∈ E[G]
            6       do if d[v] > d[u] + w(u, v)
            7             then return FALSE
            8  return TRUE

            Figure 24.4 shows the execution of the Bellman-Ford algorithm on a graph with 5 vertices. After initializing the dand π values of all vertices in line 1, the algorithm makes |V| – 1 passes over the edges of the graph. Each pass is one iteration of the for loop of lines 2-4 and consists of relaxing each edge of the graph once. Figures 24.4(b)-(e) show the state of the algorithm after each of the four passes over the edges. After making |V|- 1 passes, lines 5-8 check for a negative-weight cycle and return the appropriate boolean value. (We’ll see a little later why this check works.)

            (單擊圖片可以放大)

            Figure 24.4: The execution of the Bellman-Ford algorithm. The source is vertex s. The d values are shown within the vertices, and shaded edges indicate predecessor values: if edge (u, v) is shaded, then π[v] = u. In this particular example, each pass relaxes the edges in the order (t, x), (t, y), (t, z), (x, t), (y, x), (y, z), (z, x), (z, s), (s, t), (s, y). (a) The situation just before the first pass over the edges. (b)-(e) The situation after each successive pass over the edges. The d and π values in part (e) are the final values. The Bellman-Ford algorithm returns TRUE in this example.

            The Bellman-Ford algorithm runs in time O(V E), since the initialization in line 1 takes Θ(V) time, each of the |V| – 1 passes over the edges in lines 2-4 takes Θ(E) time, and the for loop of lines 5-7 takes O(E) time.

            以下是Bellman-Ford代碼:

            /*
            * About:  Bellman-Ford算法
            * Author: Tanky Woo
            * Blog:   www.WuTianqi.com
            */
             
            #include 
            <iostream>
            using namespace std;
            const int maxnum = 100;
            const int maxint = 99999;
             
            // 邊,
            typedef struct Edge{
                
            int u, v;    // 起點,重點
                int weight;  // 邊的權(quán)值
            }Edge;
             
            Edge edge[maxnum];     
            // 保存邊的值
            int  dist[maxnum];     // 結(jié)點到源點最小距離
             
            int nodenum, edgenum, source;    // 結(jié)點數(shù),邊數(shù),源點
             
            // 初始化圖
            void init()
            {
                
            // 輸入結(jié)點數(shù),邊數(shù),源點
                cin >> nodenum >> edgenum >> source;
                
            for(int i=1; i<=nodenum; ++i)
                    dist[i] 
            = maxint;
                dist[source] 
            = 0;
                
            for(int i=1; i<=edgenum; ++i)
                {
                    cin 
            >> edge[i].u >> edge[i].v >> edge[i].weight;
                    
            if(edge[i].u == source)          //注意這里設(shè)置初始情況
                        dist[edge[i].v] = edge[i].weight;
                }
            }
             
            // 松弛計算
            void relax(int u, int v, int weight)
            {
                
            if(dist[v] > dist[u] + weight)
                    dist[v] 
            = dist[u] + weight;
            }
             
            bool Bellman_Ford()
            {
                
            for(int i=1; i<=nodenum-1++i)
                    
            for(int j=1; j<=edgenum; ++j)
                        relax(edge[j].u, edge[j].v, edge[j].weight);
                
            bool flag = 1;
                
            // 判斷是否有負環(huán)路
                for(int i=1; i<=edgenum; ++i)
                    
            if(dist[edge[i].v] > dist[edge[i].u] + edge[i].weight)
                    {
                        flag 
            = 0;
                        
            break;
                    }
                
            return flag;
            }
            int main()
            {
                
            //freopen("input3.txt", "r", stdin);
                init();
                
            if(Bellman_Ford())
                    
            for(int i = 1 ;i <= nodenum; i++)
                        cout 
            << dist[i] << endl;
                
            return 0;
            }
            posted on 2011-01-17 20:48 Tanky Woo 閱讀(4583) 評論(2)  編輯 收藏 引用

            FeedBack:
            # re: 最短路徑算法—Bellman-Ford(貝爾曼-福特)算法分析與實現(xiàn)(C/C++) 2011-01-19 17:35 flagman
            Boost的關(guān)于圖論的Graph庫里,就有基于bellmanford的實現(xiàn),而且是可配置的。  回復(fù)  更多評論
              
            # re: 最短路徑算法—Bellman-Ford(貝爾曼-福特)算法分析與實現(xiàn)(C/C++) 2013-02-13 19:40 
            即使自己今天的狀態(tài)大多是基于在計算機上面的過程當中尋找屬于自己的想法的或者閱讀習(xí)慣的過程,從而在紀錄當中保持自己對于狀態(tài)的實際需要的平衡,而關(guān)于對于工作需要的關(guān)注實際上還沒有一個能夠被實現(xiàn)的需要  回復(fù)  更多評論
              

            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            亚洲嫩草影院久久精品| 亚洲av伊人久久综合密臀性色| 99精品久久精品| 亚洲欧美精品伊人久久| 久久这里有精品| 99国产精品久久| 一本一道久久a久久精品综合 | 狠狠色丁香久久婷婷综合_中 | 久久亚洲AV成人无码软件| 一本色道久久88—综合亚洲精品| 国产精品视频久久| 欧美日韩精品久久久久| 国产精品一区二区久久精品| 国产综合免费精品久久久| 精品久久久久久国产| 99久久精品免费看国产| 777午夜精品久久av蜜臀| 天天综合久久久网| 日产精品99久久久久久| 久久无码人妻精品一区二区三区| 无码AV波多野结衣久久| 2021国产精品午夜久久| 久久久久国产精品嫩草影院| 精品精品国产自在久久高清| 久久99热这里只有精品国产| 中文国产成人精品久久亚洲精品AⅤ无码精品 | 欧美粉嫩小泬久久久久久久 | 精品伊人久久久| 久久精品国产一区二区三区不卡| 成人国内精品久久久久一区| 久久婷婷五月综合色高清| 亚洲综合日韩久久成人AV| 伊人久久亚洲综合影院| 亚洲国产成人精品女人久久久 | 99久久久久| 国产精品久久久久9999| 久久久久无码精品国产| 久久九九精品99国产精品| 久久精品亚洲一区二区三区浴池| 日产精品久久久一区二区| 久久久久亚洲av无码专区|