overview
The Bellman-Ford algorithm is an algorithm used to find the shortest path from one vertex to the other vertices in a weighted graph. Same problem, but Bellman-Ford algorithm is slower than Dijsktra algorithm but more versatile in that it can work on graphs with negative weighted edges . The algorithm was first proposed by Alfonso Shimbel (1955), but named after Richard Bellman and Lester Ford Jr. The two published the algorithm in 1958 and 1956, respectively.
Technical
Question
Given the following graph:
Find the shortest path between vertex 1 and the rest of the vertices in the graph.
If the graph has negative weight edges, the implementation of the classic Dijkstra shortest path algorithm will fail. The improved implementation will help Dijkstra’s algorithm to overcome this problem. However, when the graph has negative cycles, this improved implementation also cannot be used because the algorithm will perform an infinite loop.
The Bellman Ford algorithm solves this problem. The main idea is very simple that is
Algorithm description
We consider an example with a graph with an upper direction (assuming the paths are one-way, only going from the vertex with the lower sequence number to the vertex with the higher order number, the red number next to each vertex is the length of the path. shortest path from root to that vertex, and root vertex is vertex 1).
Initialization:
Performing the first traversal, we can update the shortest path through edges (1, 2); (1, 3); (1, 4):
Similar to the 2nd pass, edges (2, 5) and (3, 4) are optimal edges:
With the 3rd pass, only the edge (4, 5) improves the optimal path:
By the 4th traverse, we see that there are no longer any edges that can optimize any shortest path. At this point, we can completely stop the traversal (because surely no more optimal edges means there are no negative cycles in the graph).
Pseudo code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | function <span class="token function">BellmanFord</span> <span class="token punctuation">(</span> danh_sách_đỉnh <span class="token punctuation">,</span> danh_sách_cung <span class="token punctuation">,</span> nguồn <span class="token punctuation">)</span> <span class="token comment">// hàm yêu cầu đồ thị đưa vào dưới dạng một danh sách đỉnh, một danh sách cung</span> <span class="token comment">// hàm tính các giá trị khoảng_cách và đỉnh_liền_trước của các đỉnh,</span> <span class="token comment">// sao cho các giá trị đỉnh_liền_trước sẽ lưu lại các đường đi ngắn nhất.</span> <span class="token comment">// bước 1: khởi tạo đồ thị</span> <span class="token keyword">for</span> each v in danh_sách_đỉnh <span class="token operator">:</span> <span class="token keyword">if</span> v is nguồn then khoảng_cá <span class="token function">ch</span> <span class="token punctuation">(</span> v <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token operator">=</span> <span class="token number">0</span> <span class="token keyword">else</span> khoảng_cá <span class="token function">ch</span> <span class="token punctuation">(</span> v <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token operator">=</span> vô cùng đỉnh_liền_trướ <span class="token function">c</span> <span class="token punctuation">(</span> v <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token operator">=</span> null <span class="token comment">// bước 2: kết nạp cạnh</span> <span class="token keyword">for</span> i from <span class="token number">1</span> to <span class="token function">size</span> <span class="token punctuation">(</span> danh_sách_đỉnh <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">1</span> <span class="token operator">:</span> <span class="token keyword">for</span> <span class="token function">each</span> <span class="token punctuation">(</span> u <span class="token punctuation">,</span> v <span class="token punctuation">)</span> in danh_sách_cung <span class="token operator">:</span> <span class="token keyword">if</span> khoảng_cá <span class="token function">ch</span> <span class="token punctuation">(</span> v <span class="token punctuation">)</span> <span class="token operator">></span> khoảng_cá <span class="token function">ch</span> <span class="token punctuation">(</span> u <span class="token punctuation">)</span> <span class="token operator">+</span> trọng_số <span class="token punctuation">(</span> u <span class="token punctuation">,</span> v <span class="token punctuation">)</span> <span class="token operator">:</span> khoảng_cá <span class="token function">ch</span> <span class="token punctuation">(</span> v <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token operator">=</span> khoảng_cá <span class="token function">ch</span> <span class="token punctuation">(</span> u <span class="token punctuation">)</span> <span class="token operator">+</span> trọng_số <span class="token punctuation">(</span> u <span class="token punctuation">,</span> v <span class="token punctuation">)</span> đỉnh_liền_trướ <span class="token function">c</span> <span class="token punctuation">(</span> v <span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token operator">=</span> u <span class="token comment">// bước 3: kiểm tra chu trình âm</span> <span class="token keyword">for</span> <span class="token function">each</span> <span class="token punctuation">(</span> u <span class="token punctuation">,</span> v <span class="token punctuation">)</span> in danh_sách_cung <span class="token operator">:</span> <span class="token keyword">if</span> khoảng_cá <span class="token function">ch</span> <span class="token punctuation">(</span> v <span class="token punctuation">)</span> <span class="token operator">></span> khoảng_cá <span class="token function">ch</span> <span class="token punctuation">(</span> u <span class="token punctuation">)</span> <span class="token operator">+</span> trọng_số <span class="token punctuation">(</span> u <span class="token punctuation">,</span> v <span class="token punctuation">)</span> <span class="token operator">:</span> error <span class="token string">"Đồ thị chứa chu trình âm"</span> |
Setting
Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | <span class="token comment">// Thuat toan voi do thi khong co chu trinh am</span> <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><bits/stdc++.h></span></span> <span class="token keyword">using</span> <span class="token keyword">namespace</span> std <span class="token punctuation">;</span> <span class="token keyword">typedef</span> pair <span class="token operator"><</span> <span class="token keyword">int</span> <span class="token punctuation">,</span> <span class="token keyword">int</span> <span class="token operator">></span> ii <span class="token punctuation">;</span> vector <span class="token operator"><</span> ii <span class="token operator">></span> a <span class="token punctuation">[</span> <span class="token number">181220</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span> <span class="token keyword">int</span> n <span class="token punctuation">,</span> m <span class="token punctuation">;</span> <span class="token keyword">int</span> d <span class="token punctuation">[</span> <span class="token number">181220</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span> <span class="token keyword">bool</span> inqueue <span class="token punctuation">[</span> <span class="token number">181220</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span> <span class="token keyword">int</span> pre <span class="token punctuation">[</span> <span class="token number">181220</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span> vector <span class="token operator"><</span> <span class="token keyword">int</span> <span class="token operator">></span> path <span class="token punctuation">;</span> <span class="token keyword">void</span> <span class="token function">bellman</span> <span class="token punctuation">(</span> <span class="token keyword">int</span> u <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">//Buoc 1: Khoi tao</span> queue <span class="token operator"><</span> <span class="token keyword">int</span> <span class="token operator">></span> qu <span class="token punctuation">;</span> <span class="token keyword">for</span> <span class="token punctuation">(</span> <span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">1</span> <span class="token punctuation">;</span> i <span class="token operator"><=</span> n <span class="token punctuation">;</span> i <span class="token operator">++</span> <span class="token punctuation">)</span> d <span class="token punctuation">[</span> i <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">99999999</span> <span class="token punctuation">;</span> d <span class="token punctuation">[</span> u <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">0</span> <span class="token punctuation">;</span> qu <span class="token punctuation">.</span> <span class="token function">push</span> <span class="token punctuation">(</span> u <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">//push u vào queue</span> inqueue <span class="token punctuation">[</span> u <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">true</span> <span class="token punctuation">;</span> <span class="token comment">//Đánh dấu đỉnh u đã trong queue</span> <span class="token comment">// Buoc 2: Lap</span> <span class="token keyword">while</span> <span class="token punctuation">(</span> qu <span class="token punctuation">.</span> <span class="token function">size</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> u <span class="token operator">=</span> qu <span class="token punctuation">.</span> <span class="token function">front</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">//Lấy giá trị đầu của queue</span> inqueue <span class="token punctuation">[</span> u <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">false</span> <span class="token punctuation">;</span> <span class="token comment">//Đánh dấu là đỉnh u đã pop ra khỏi queue (hay không còn trong queue)</span> qu <span class="token punctuation">.</span> <span class="token function">pop</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// pop đỉnh u ra khỏi queue</span> <span class="token keyword">for</span> <span class="token punctuation">(</span> <span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span> <span class="token punctuation">;</span> i <span class="token operator"><</span> a <span class="token punctuation">[</span> u <span class="token punctuation">]</span> <span class="token punctuation">.</span> <span class="token function">size</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> i <span class="token operator">++</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Duyệt các đỉnh kề u</span> <span class="token keyword">int</span> v <span class="token operator">=</span> a <span class="token punctuation">[</span> u <span class="token punctuation">]</span> <span class="token punctuation">[</span> i <span class="token punctuation">]</span> <span class="token punctuation">.</span> second <span class="token punctuation">;</span> <span class="token keyword">int</span> uv <span class="token operator">=</span> a <span class="token punctuation">[</span> u <span class="token punctuation">]</span> <span class="token punctuation">[</span> i <span class="token punctuation">]</span> <span class="token punctuation">.</span> first <span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> d <span class="token punctuation">[</span> v <span class="token punctuation">]</span> <span class="token operator">></span> d <span class="token punctuation">[</span> u <span class="token punctuation">]</span> <span class="token operator">+</span> uv <span class="token punctuation">)</span> <span class="token punctuation">{</span> d <span class="token punctuation">[</span> v <span class="token punctuation">]</span> <span class="token operator">=</span> d <span class="token punctuation">[</span> u <span class="token punctuation">]</span> <span class="token operator">+</span> uv <span class="token punctuation">;</span> pre <span class="token punctuation">[</span> v <span class="token punctuation">]</span> <span class="token operator">=</span> u <span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token operator">!</span> inqueue <span class="token punctuation">[</span> v <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Nếu đỉnh v chưa trong queue</span> qu <span class="token punctuation">.</span> <span class="token function">push</span> <span class="token punctuation">(</span> v <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// Cho v vào queue</span> inqueue <span class="token punctuation">[</span> v <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">true</span> <span class="token punctuation">;</span> <span class="token comment">// Đánh dấu là đỉnh v đã trong queue</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">int</span> <span class="token function">main</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">int</span> u <span class="token punctuation">,</span> v <span class="token punctuation">;</span> <span class="token comment">// dinh nguon va dinh dich</span> <span class="token function">scanf</span> <span class="token punctuation">(</span> <span class="token string">"%d%d%d%d"</span> <span class="token punctuation">,</span> <span class="token operator">&</span> n <span class="token punctuation">,</span> <span class="token operator">&</span> m <span class="token punctuation">,</span> <span class="token operator">&</span> u <span class="token punctuation">,</span> <span class="token operator">&</span> v <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">while</span> <span class="token punctuation">(</span> m <span class="token operator">--</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">int</span> p <span class="token punctuation">,</span> q <span class="token punctuation">,</span> w <span class="token punctuation">;</span> <span class="token function">scanf</span> <span class="token punctuation">(</span> <span class="token string">"%d%d%d"</span> <span class="token punctuation">,</span> <span class="token operator">&</span> p <span class="token punctuation">,</span> <span class="token operator">&</span> q <span class="token punctuation">,</span> <span class="token operator">&</span> w <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// Do thi vo huong</span> a <span class="token punctuation">[</span> p <span class="token punctuation">]</span> <span class="token punctuation">.</span> <span class="token function">push_back</span> <span class="token punctuation">(</span> <span class="token function">ii</span> <span class="token punctuation">(</span> w <span class="token punctuation">,</span> q <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> a <span class="token punctuation">[</span> q <span class="token punctuation">]</span> <span class="token punctuation">.</span> <span class="token function">push_back</span> <span class="token punctuation">(</span> <span class="token function">ii</span> <span class="token punctuation">(</span> w <span class="token punctuation">,</span> p <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token function">bellman</span> <span class="token punctuation">(</span> u <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">printf</span> <span class="token punctuation">(</span> <span class="token string">"%dn"</span> <span class="token punctuation">,</span> d <span class="token punctuation">[</span> v <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">for</span> <span class="token punctuation">(</span> <span class="token keyword">int</span> i <span class="token operator">=</span> v <span class="token punctuation">;</span> i <span class="token operator">!=</span> u <span class="token punctuation">;</span> i <span class="token operator">=</span> pre <span class="token punctuation">[</span> i <span class="token punctuation">]</span> <span class="token punctuation">)</span> path <span class="token punctuation">.</span> <span class="token function">push_back</span> <span class="token punctuation">(</span> i <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// them dinh vao duong di</span> path <span class="token punctuation">.</span> <span class="token function">push_back</span> <span class="token punctuation">(</span> u <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">reverse</span> <span class="token punctuation">(</span> path <span class="token punctuation">.</span> <span class="token function">begin</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> path <span class="token punctuation">.</span> <span class="token function">end</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">printf</span> <span class="token punctuation">(</span> <span class="token string">"Duong di: "</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">for</span> <span class="token punctuation">(</span> <span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span> <span class="token punctuation">;</span> i <span class="token operator"><</span> path <span class="token punctuation">.</span> <span class="token function">size</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> i <span class="token operator">++</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> i <span class="token operator">==</span> path <span class="token punctuation">.</span> <span class="token function">size</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">1</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">printf</span> <span class="token punctuation">(</span> <span class="token string">"%d"</span> <span class="token punctuation">,</span> v <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">break</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token function">printf</span> <span class="token punctuation">(</span> <span class="token string">"%d -> "</span> <span class="token punctuation">,</span> path <span class="token punctuation">[</span> i <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
- Best case time complexity:
O (E ) O(|E|) - Average time complexity:
O (E .DRAW ) O(|E|.|V|) - Worst case time complexity:
O (E .DRAW ) O(|E|.|V|)
Algorithm application
A distributed variant of the Bellman-Ford algorithm used in distance vector routing protocols, such as the Routing Information Protocol (RIP). This is the distributed variant because it involves network nodes (routers) in an automated system, i.e. a set of IP networks owned by an Internet service provider. (ISPs).
The algorithm consists of the following steps:
- Each node calculates the distance between it and all other nodes in the automated system and stores this information in a table.
- Each node sends its information table to all neighboring nodes.
- When a node receives information tables from neighboring nodes, it computes the shortest routes to all other nodes and updates its own table of information.
The main disadvantages of the Bellman-Ford algorithm in this configuration are:
- Doesn’t scale well.
- Network topology changes are not recorded as quickly as updates are propagated node-by-node.
- Counting to infinity (if a broken link or broken network node causes a node to be separated from a set of other nodes, these nodes will continue to estimate the distance to that node and increase the calculated value, in then circular routing is also possible).
summary
Graph features | BFS O ( DRAW + E ) O(V+E) | Dijsktra O ( ( DRAW + E ) log DRAW ) O((V+E) log V) | Bellman Ford O ( DRAW E ) O(VE) | Floyd Warshall O ( DRAW 3 ) O(V^3) |
---|---|---|---|---|
Graph size applicable | DRAW , E ten USA V,E le 10M | DRAW , E 300 KY V,E le 300K | DRAW E ten USA VE le 10M | DRAW 400 V le 400 |
Unweighted | The best | Fine | Bad | Mostly bad |
Weighted | WA | The best | Fine | Mostly bad |
Negative weights | WA | Fine | Fine | Mostly bad |
Negative cycle | Unable to determine | Unable to determine | Identifiable | Identifiable |
Minigraphs | WA if weighted | Take a buffalo knife to kill chickens | Take delivery of buffalo to kill chickens | The best |
References
- Algorithms and Programming – Teacher Le Minh Hoang
- cp-algorithms.com
- Handbook Competitive Programming – Antti Laaksonen
- Competitve programming 3 – Steven Halim, Felix Halim
- https://sites.google.com/site/kc97ble/algorithm-graph/fordbellmanqueue-cpp