00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <vector>
00015
00016 #include "base/callback.h"
00017 #include "base/integral_types.h"
00018 #include "base/scoped_ptr.h"
00019
00020 namespace operations_research {
00021 class BellmanFord {
00022 public:
00023 static const int64 kInfinity = kint64max / 2;
00024
00025 BellmanFord(int node_count,
00026 int start_node,
00027 ResultCallback2<int64, int, int>* const graph,
00028 int64 disconnected_distance)
00029 : node_count_(node_count),
00030 start_node_(start_node),
00031 graph_(graph),
00032 disconnected_distance_(disconnected_distance),
00033 distance_(new int64[node_count_]),
00034 predecessor_(new int[node_count_]) {
00035 graph->CheckIsRepeatable();
00036 }
00037 bool ShortestPath(int end_node, std::vector<int>* nodes);
00038 private:
00039 void Initialize();
00040 void Update();
00041 bool Check() const;
00042 void FindPath(int dest, std::vector<int>* nodes) const;
00043
00044 const int node_count_;
00045 const int start_node_;
00046 scoped_ptr<ResultCallback2<int64, int, int> > graph_;
00047 const int64 disconnected_distance_;
00048 scoped_array<int64> distance_;
00049 scoped_array<int> predecessor_;
00050 };
00051
00052 void BellmanFord::Initialize() {
00053 for (int i = 0; i < node_count_; i++) {
00054 distance_[i] = kint64max / 2;
00055 predecessor_[i] = -1;
00056 }
00057 distance_[start_node_] = 0;
00058 }
00059
00060 void BellmanFord::Update() {
00061 for (int i = 0; i < node_count_ - 1; i++) {
00062 for (int u = 0; u < node_count_; u++) {
00063 for (int v = 0; v < node_count_; v++) {
00064 const int64 graph_u_v = graph_->Run(u, v);
00065 if (graph_u_v != disconnected_distance_) {
00066 const int64 other_distance = distance_[u] + graph_u_v;
00067 if (distance_[v] > other_distance) {
00068 distance_[v] = other_distance;
00069 predecessor_[v] = u;
00070 }
00071 }
00072 }
00073 }
00074 }
00075 }
00076
00077 bool BellmanFord::Check() const {
00078 for (int u = 0; u < node_count_; u++) {
00079 for (int v = 0; v < node_count_; v++) {
00080 const int graph_u_v = graph_->Run(u, v);
00081 if (graph_u_v != disconnected_distance_) {
00082 if (distance_[v] > distance_[u] + graph_u_v) {
00083 return false;
00084 }
00085 }
00086 }
00087 }
00088 return true;
00089 }
00090
00091 void BellmanFord::FindPath(int dest, std::vector<int>* nodes) const {
00092 int j = dest;
00093 nodes->push_back(j);
00094 while (predecessor_[j] != -1) {
00095 nodes->push_back(predecessor_[j]);
00096 j = predecessor_[j];
00097 }
00098 }
00099
00100 bool BellmanFord::ShortestPath(int end_node, std::vector<int>* nodes) {
00101 Initialize();
00102 Update();
00103 if (distance_[end_node] == kInfinity) {
00104 return false;
00105 }
00106 if (!Check()) {
00107 return false;
00108 }
00109 FindPath(end_node, nodes);
00110 return true;
00111 }
00112
00113 bool BellmanFordShortestPath(int node_count,
00114 int start_node,
00115 int end_node,
00116 ResultCallback2<int64, int, int>* const graph,
00117 int64 disconnected_distance,
00118 std::vector<int>* nodes) {
00119 BellmanFord bf(node_count, start_node, graph, disconnected_distance);
00120 return bf.ShortestPath(end_node, nodes);
00121 }
00122 }