Skip to content

Commit

Permalink
fix bellman ford
Browse files Browse the repository at this point in the history
  • Loading branch information
ei1333 committed Jun 11, 2024
1 parent 6b121a2 commit 2aa52ad
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 23 deletions.
23 changes: 15 additions & 8 deletions docs/bellman-ford.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
---
documentation_of: //graph/shortest-path/bellman-ford.hpp
title: Bellman-Ford (単一始点最短路)
documentation_of: //graph/shortest-path/dijkstra.hpp
---

## 概要
単一始点全点間最短路を求めるアルゴリズムです。負辺があっても動作します。経路上に負閉路がある場合はそれを検出します。

単一始点全点間最短路を求めるアルゴリズム. 負辺があっても動作する. また負閉路も検出する.
# bellman_ford

負閉路がない場合, 全ての頂点への最短路に含まれる辺の本数は $V - 1$ 本以下である. したがって $V - 1$ 回すべての辺を走査して最短路を更新すると, 最終的な最短路が求まる.
```cpp
template <typename T>
vector<T> bellman_ford(const Edges<T> &edges, int n, int s)
```
負閉路がある場合 $V$ 回目に更新があるときだが, 始点とある頂点との $2$ 点間のパスに負閉路が含まれることと同値ではないので注意すること(これを判定した場合は負閉路からその頂点に到達可能か判定するか, 始点とある頂点から到達できない頂点を予め削除しておく必要がある, 実装しなさーい!).
頂点数 $n$ 、辺集合が `edges` からなる有向グラフについて、始点 $s$ から各頂点への最短路の重みを求め、それを返します。
## 使い方
* `bellman_ford(g, V, s)`: `V` 頂点の重み付きグラフ `g` で, 頂点 `s` から全点間の最短コストを求める.
ただし、始点 $s$ からその頂点に到達できない場合は `T` の最大値、その頂点までの経路上に負閉路が存在する場合は `T` の最小値が格納されます。
## 制約
- $0 \leq s \lt n$
## 計算量
* $O(VE)$
* $O(V E)$
2 changes: 1 addition & 1 deletion docs/longest-common-substring.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ $s$ と $t$ の最長共通部分列を $S[a, b)$、$T[c, d)$ とします。こ
## 計算量
$n = \max(|s|, |t|)$ とします。
$n = \max(\|s\|, \|t\|)$ とします。
- `compress = false`: $O(n)$
- `compress = true`: $O(n \log n)$
2 changes: 1 addition & 1 deletion docs/static-rectangle-add-rectangle-sum.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ documentation_of: //other/static-rectangle-add-rectangle-sum.hpp

(2) で長方形の個数 $n$、クエリの個数 $q$ を指定した場合、領域を `reserve` するので少しだけ効率的です。

# add_point
# add_rectangle

```cpp
void add_rectangle(T l, T d, T r, T u, C w)
Expand Down
31 changes: 19 additions & 12 deletions graph/shortest-path/bellman-ford.hpp
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
#pragma once

#include "../graph-template.hpp"

/**
* @brief Bellman-Ford(単一始点最短路)
*
*/
template <typename T>
vector<T> bellman_ford(const Edges<T> &edges, int V, int s) {
vector<T> bellman_ford(const Edges<T> &edges, int n, int s) {
const auto INF = numeric_limits<T>::max();
vector<T> dist(V, INF);
const auto M_INF = numeric_limits<T>::min();
vector<T> dist(n, INF);
dist[s] = 0;
for (int i = 0; i < V - 1; i++) {
for (int i = 0; i < n - 1; i++) {
for (auto &e : edges) {
if (dist[e.from] == INF) continue;
dist[e.to] = min(dist[e.to], dist[e.from] + e.cost);
}
}
for (auto &e : edges) {
if (dist[e.from] == INF) continue;
if (dist[e.from] + e.cost < dist[e.to]) return vector<T>();
vector<bool>negative(n);
for(int i = 0; i < n; i++) {
for (auto &e: edges) {
if (dist[e.from] == INF) continue;
if (dist[e.from] + e.cost < dist[e.to]) {
dist[e.to] = dist[e.from] + e.cost;
negative[e.to] = true;
}
if(negative[e.from]) {
negative[e.to] = true;
}
}
}
for(int i = 0; i < n; i++) {
if(negative[i]) dist[i] = M_INF;
}
return dist;
}
7 changes: 6 additions & 1 deletion test/verify/aoj-grl-1-b.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ int main() {
es.emplace_back(a, b, c);
}
auto dists = bellman_ford(es, V, R);
if(dists.empty()) cout << "NEGATIVE CYCLE\n";
for(auto& dist : dists) {
if(dist == numeric_limits< int >::min()) {
cout << "NEGATIVE CYCLE\n";
return 0;
}
}
for(auto &dist : dists) {
if(dist == numeric_limits< int >::max()) cout << "INF\n";
else cout << dist << "\n";
Expand Down

0 comments on commit 2aa52ad

Please sign in to comment.