//======================================================================= // Copyright 1997, 1998, 1999, 2000 University of Notre Dame. // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) //======================================================================= #include #include #include #include #include // Use boost::queue instead of std::queue because std::queue doesn't // model Buffer; it has to top() function. -Jeremy #include #include #include #include #include #include using namespace std; using namespace boost; /* This example does a best-first-search (using dijkstra's) and simultaneously makes a copy of the graph (assuming the graph is connected). Example Graph: (p. 90 "Data Structures and Network Algorithms", Tarjan) g 3+ +2 / 1 \ e+----f |+0 5++ | \ / | 10| d |12 |8++\7| +/ | +| b 4| c \ | + 6+|/3 a Sample Output: a --> c d b --> a d c --> f d --> c e f e --> b g f --> e g g --> Starting graph: a(32767); c d c(32767); f d(32767); c e f f(32767); e g e(32767); b g g(32767); b(32767); a d Result: a(0); d c d(4); f e c c(3); f f(9); g e e(4); g b g(7); b(14); d a */ typedef property > VProperty; typedef int weight_t; typedef property EProperty; typedef adjacency_list Graph; template struct endl_printer : public boost::base_visitor< endl_printer > { typedef Tag event_filter; endl_printer(std::ostream& os) : m_os(os) { } template void operator()(T, Graph&) { m_os << std::endl; } std::ostream& m_os; }; template endl_printer print_endl(std::ostream& os, Tag) { return endl_printer(os); } template struct edge_printer : public boost::base_visitor< edge_printer > { typedef Tag event_filter; edge_printer(PA pa, std::ostream& os) : m_pa(pa), m_os(os) { } template void operator()(T x, Graph& g) { m_os << "(" << get(m_pa, source(x, g)) << "," << get(m_pa, target(x, g)) << ") "; } PA m_pa; std::ostream& m_os; }; template edge_printer print_edge(PA pa, std::ostream& os, Tag) { return edge_printer(pa, os); } template struct graph_copier : public boost::base_visitor > { typedef Tag event_filter; graph_copier(NewGraph& graph) : new_g(graph) { } template void operator()(Edge e, Graph& g) { add_edge(source(e, g), target(e, g), new_g); } private: NewGraph& new_g; }; template inline graph_copier copy_graph(NewGraph& g, Tag) { return graph_copier(g); } template void print(Graph& G, Name name) { typename boost::graph_traits::vertex_iterator ui, uiend; for (boost::tie(ui, uiend) = vertices(G); ui != uiend; ++ui) { cout << name[*ui] << " --> "; typename boost::graph_traits::adjacency_iterator vi, viend; for(boost::tie(vi, viend) = adjacent_vertices(*ui, G); vi != viend; ++vi) cout << name[*vi] << " "; cout << endl; } } int main(int , char* []) { // Name and ID numbers for the vertices char name[] = "abcdefg"; enum { a, b, c, d, e, f, g, N}; Graph G(N); boost::property_map::type vertex_id = get(vertex_index, G); std::vector distance(N, (numeric_limits::max)()); typedef boost::graph_traits::vertex_descriptor Vertex; std::vector parent(N); typedef std::pair E; E edges[] = { E(a,c), E(a,d), E(b,a), E(b,d), E(c,f), E(d,c), E(d,e), E(d,f), E(e,b), E(e,g), E(f,e), E(f,g) }; int weight[] = { 3, 4, 6, 8, 12, 7, 0, 5, 10, 3, 1, 2 }; for (int i = 0; i < 12; ++i) add_edge(edges[i].first, edges[i].second, weight[i], G); print(G, name); adjacency_list > G_copy(N); cout << "Starting graph:" << endl; std::ostream_iterator cout_int(std::cout, " "); std::ostream_iterator cout_char(std::cout, " "); boost::queue Q; boost::breadth_first_search (G, vertex(a, G), Q, make_bfs_visitor( boost::make_list (write_property(make_iterator_property_map(name, vertex_id, name[0]), cout_char, on_examine_vertex()), write_property(make_iterator_property_map(distance.begin(), vertex_id, distance[0]), cout_int, on_examine_vertex()), print_edge(make_iterator_property_map(name, vertex_id, name[0]), std::cout, on_examine_edge()), print_endl(std::cout, on_finish_vertex()))), get(vertex_color, G)); std::cout << "about to call dijkstra's" << std::endl; parent[vertex(a, G)] = vertex(a, G); boost::dijkstra_shortest_paths (G, vertex(a, G), distance_map(make_iterator_property_map(distance.begin(), vertex_id, distance[0])). predecessor_map(make_iterator_property_map(parent.begin(), vertex_id, parent[0])). visitor(make_dijkstra_visitor(copy_graph(G_copy, on_examine_edge())))); cout << endl; cout << "Result:" << endl; boost::breadth_first_search (G, vertex(a, G), visitor(make_bfs_visitor( boost::make_list (write_property(make_iterator_property_map(name, vertex_id, name[0]), cout_char, on_examine_vertex()), write_property(make_iterator_property_map(distance.begin(), vertex_id, distance[0]), cout_int, on_examine_vertex()), print_edge(make_iterator_property_map(name, vertex_id, name[0]), std::cout, on_examine_edge()), print_endl(std::cout, on_finish_vertex()))))); return 0; }