読者です 読者をやめる 読者になる 読者になる

ベルマンフォードアルゴリズムをC++で

アルゴリズム C++

アルゴリズムの経過をアニメーションgifにするために書いたはいいものの、アルゴリズムとは関係ないコードが増えてしまったので、C++で書き直してみた。以下コード。

#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <math.h>

using namespace std;

class DirectedGraph {
public:
  DirectedGraph() {
  };
  virtual ~DirectedGraph() {
  };
  void add_node(string v) {
	if (find(nodes.begin(), nodes.end(), v) == nodes.end())  
	  nodes.push_back(v);
  };
  void add_edge(string u, string v, double w){
	add_node(u);
	add_node(v);
	map<string, string> edge;
	edge.insert(pair<string, string>(u, v));
	weights.insert(pair<map<string, string>, double>(edge, w));	
  };
  bool bellman_ford(string s){
	// initialization
	map<string, double> d;
	map<string, string> pi;
	for (vector<string>::iterator it = nodes.begin(); it != nodes.end(); ++it) {
	  d[*it] = HUGE_VAL;
	  pi[*it] = "\0";
	}
	d[s] = 0.0;
	for (unsigned int i = 0; i < nodes.size() - 1; ++i) {
	  for (map<map<string, string>, double>::iterator it = weights.begin(); it != weights.end(); ++it) {
		string u = (*it).first.begin()->first;
		string v = (*it).first.begin()->second;
		double w = (*it).second;
		// relax
		if (d[v] > d[u] + w) {
		  d[v] = d[u] + w;
		  pi[v] = u;
		}
	  }
	}
	for (map<map<string, string>, double>::iterator it = weights.begin(); it != weights.end(); ++it) {
	  string u = (*it).first.begin()->first;
	  string v = (*it).first.begin()->second;
	  double w = (*it).second;
	  if (d[v] > d[u] + w) 
		return false;
	}
	// print result
	for (vector<string>::iterator it = nodes.begin(); it != nodes.end(); ++it) {
	  vector<string> result;
	  string v = *it;
	  while(v != s) {
		result.push_back(v);
		v = pi[v];
	  }
	  reverse(result.begin(), result.end());
	  result.insert(result.begin(), s);
	  unsigned int i = 0;
	  for (vector<string>::iterator node_itr = result.begin(); node_itr != result.end(); ++node_itr) {
		if (i < result.size() - 1) {
		  cout << *node_itr << " -> ";
		} else {
		  cout << *node_itr;
		}
		i++;
	  }
	  cout << " (" << d[*it] << ")" << endl;
	}
	return true;
  };
private:
  vector<string> nodes;
  map<map<string, string>, double> weights;
};

int main (int argc, char **argv) {
  DirectedGraph g;
  g.add_edge("a", "b", 6.0);
  g.add_edge("a", "c", 7.0);
  g.add_edge("b", "d", 5);
  g.add_edge("b", "e", -4.0);
  g.add_edge("b", "c", 8.0);
  g.add_edge("c", "d", -3.0);
  g.add_edge("c", "e", 9.0);
  g.add_edge("d", "b", -2);
  g.add_edge("e", "d", 7.0);
  g.add_edge("e", "a", 2.0);
  g.bellman_ford("a");
  return 0;
}

実行結果

/Users/syou6162/discrete_optimization_theory% ./a.out                   
a (0)
a -> c -> d -> b (2)
a -> c (7)
a -> c -> d (4)
a -> c -> d -> b -> e (-2)