kevin-bacon.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. //=======================================================================
  2. // Copyright 2001 Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee,
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See
  5. // accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //=======================================================================
  8. #include <boost/config.hpp>
  9. #include <iostream>
  10. #include <fstream>
  11. #include <string>
  12. #include <boost/tokenizer.hpp>
  13. #include <boost/tuple/tuple.hpp>
  14. #include <boost/graph/adjacency_list.hpp>
  15. #include <boost/graph/visitors.hpp>
  16. #include <boost/graph/breadth_first_search.hpp>
  17. #include <map>
  18. using namespace boost;
  19. template <typename DistanceMap>
  20. class bacon_number_recorder : public default_bfs_visitor
  21. {
  22. public:
  23. bacon_number_recorder(DistanceMap dist) : d(dist) { }
  24. template <typename Edge, typename Graph>
  25. void tree_edge(Edge e, const Graph& g) const
  26. {
  27. typename graph_traits<Graph>::vertex_descriptor
  28. u = source(e, g), v = target(e, g);
  29. d[v] = d[u] + 1;
  30. }
  31. private:
  32. DistanceMap d;
  33. };
  34. // Convenience function
  35. template < typename DistanceMap >
  36. bacon_number_recorder<DistanceMap>
  37. record_bacon_number(DistanceMap d)
  38. {
  39. return bacon_number_recorder < DistanceMap > (d);
  40. }
  41. int
  42. main(int argc, const char** argv)
  43. {
  44. std::ifstream datafile(argc >= 2 ? argv[1] : "./kevin-bacon.dat");
  45. if (!datafile) {
  46. std::cerr << "No ./kevin-bacon.dat file" << std::endl;
  47. return EXIT_FAILURE;
  48. }
  49. typedef adjacency_list < vecS, vecS, undirectedS, property < vertex_name_t,
  50. std::string >, property < edge_name_t, std::string > > Graph;
  51. Graph g;
  52. typedef property_map < Graph, vertex_name_t >::type actor_name_map_t;
  53. actor_name_map_t actor_name = get(vertex_name, g);
  54. typedef property_map < Graph, edge_name_t >::type movie_name_map_t;
  55. movie_name_map_t connecting_movie = get(edge_name, g);
  56. typedef graph_traits < Graph >::vertex_descriptor Vertex;
  57. typedef std::map < std::string, Vertex > NameVertexMap;
  58. NameVertexMap actors;
  59. for (std::string line; std::getline(datafile, line);) {
  60. char_delimiters_separator < char >sep(false, "", ";");
  61. tokenizer <> line_toks(line, sep);
  62. tokenizer <>::iterator i = line_toks.begin();
  63. std::string actors_name = *i++;
  64. NameVertexMap::iterator pos;
  65. bool inserted;
  66. Vertex u, v;
  67. boost::tie(pos, inserted) = actors.insert(std::make_pair(actors_name, Vertex()));
  68. if (inserted) {
  69. u = add_vertex(g);
  70. actor_name[u] = actors_name;
  71. pos->second = u;
  72. } else
  73. u = pos->second;
  74. std::string movie_name = *i++;
  75. boost::tie(pos, inserted) = actors.insert(std::make_pair(*i, Vertex()));
  76. if (inserted) {
  77. v = add_vertex(g);
  78. actor_name[v] = *i;
  79. pos->second = v;
  80. } else
  81. v = pos->second;
  82. graph_traits < Graph >::edge_descriptor e;
  83. boost::tie(e, inserted) = add_edge(u, v, g);
  84. if (inserted)
  85. connecting_movie[e] = movie_name;
  86. }
  87. std::vector < int >bacon_number(num_vertices(g));
  88. Vertex src = actors["Kevin Bacon"];
  89. bacon_number[src] = 0;
  90. breadth_first_search(g, src,
  91. visitor(record_bacon_number(&bacon_number[0])));
  92. graph_traits < Graph >::vertex_iterator i, end;
  93. for (boost::tie(i, end) = vertices(g); i != end; ++i) {
  94. std::cout << actor_name[*i] << " has a Bacon number of "
  95. << bacon_number[*i] << std::endl;
  96. }
  97. return 0;
  98. }