ossrv_pub/boost_apis/boost/graph/detail/adjacency_list.hpp
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 // -*- c++ -*-
       
     2 //=======================================================================
       
     3 // Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
       
     4 // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
       
     5 //
       
     6 // Distributed under the Boost Software License, Version 1.0. (See
       
     7 // accompanying file LICENSE_1_0.txt or copy at
       
     8 // http://www.boost.org/LICENSE_1_0.txt)
       
     9 //=======================================================================
       
    10 
       
    11 #ifndef BOOST_GRAPH_DETAIL_ADJACENCY_LIST_HPP
       
    12 #define BOOST_GRAPH_DETAIL_ADJACENCY_LIST_HPP
       
    13 
       
    14 #include <map> // for vertex_map in copy_impl
       
    15 #include <boost/config.hpp>
       
    16 #include <boost/detail/workaround.hpp>
       
    17 #include <boost/operators.hpp>
       
    18 #include <boost/property_map.hpp>
       
    19 #include <boost/pending/integer_range.hpp>
       
    20 #include <boost/graph/graph_traits.hpp>
       
    21 #include <memory>
       
    22 #include <algorithm>
       
    23 #include <boost/limits.hpp>
       
    24 
       
    25 #include <boost/iterator/iterator_adaptor.hpp>
       
    26 
       
    27 #include <boost/pending/ct_if.hpp>
       
    28 #include <boost/graph/graph_concepts.hpp>
       
    29 #include <boost/pending/container_traits.hpp>
       
    30 #include <boost/graph/detail/adj_list_edge_iterator.hpp>
       
    31 #include <boost/graph/properties.hpp>
       
    32 #include <boost/pending/property.hpp>
       
    33 #include <boost/graph/adjacency_iterator.hpp>
       
    34 #include <boost/static_assert.hpp>
       
    35 
       
    36 // Symbol truncation problems with MSVC, trying to shorten names.
       
    37 #define stored_edge se_
       
    38 #define stored_edge_property sep_
       
    39 #define stored_edge_iter sei_
       
    40 
       
    41 /*
       
    42   Outline for this file:
       
    43 
       
    44   out_edge_iterator and in_edge_iterator implementation
       
    45   edge_iterator for undirected graph
       
    46   stored edge types (these object live in the out-edge/in-edge lists)
       
    47   directed edges helper class
       
    48   directed graph helper class
       
    49   undirected graph helper class
       
    50   bidirectional graph helper class
       
    51   bidirectional graph helper class (without edge properties)
       
    52   bidirectional graph helper class (with edge properties)
       
    53   adjacency_list helper class
       
    54   adj_list_impl class
       
    55   vec_adj_list_impl class
       
    56   adj_list_gen class
       
    57   vertex property map
       
    58   edge property map
       
    59 
       
    60 
       
    61   Note: it would be nice to merge some of the undirected and
       
    62   bidirectional code... it is awful similar.
       
    63  */
       
    64 
       
    65 
       
    66 namespace boost {
       
    67 
       
    68   namespace detail {
       
    69 
       
    70     template <typename DirectedS>
       
    71     struct directed_category_traits {
       
    72       typedef directed_tag directed_category;
       
    73     };
       
    74 
       
    75     template <>
       
    76     struct directed_category_traits<directedS> {
       
    77       typedef directed_tag directed_category;
       
    78     };
       
    79     template <>
       
    80     struct directed_category_traits<undirectedS> {
       
    81       typedef undirected_tag directed_category;
       
    82     };
       
    83     template <>
       
    84     struct directed_category_traits<bidirectionalS> {
       
    85       typedef bidirectional_tag directed_category;
       
    86     };
       
    87 
       
    88     template <class Vertex>
       
    89     struct target_is {
       
    90       target_is(const Vertex& v) : m_target(v) { }
       
    91       template <class StoredEdge>
       
    92       bool operator()(const StoredEdge& e) const {
       
    93         return e.get_target() == m_target;
       
    94       }
       
    95       Vertex m_target;
       
    96     };
       
    97 
       
    98     // O(E/V)
       
    99     template <class EdgeList, class vertex_descriptor>
       
   100     void erase_from_incidence_list(EdgeList& el, vertex_descriptor v,
       
   101                                    allow_parallel_edge_tag)
       
   102     {
       
   103       boost::graph_detail::erase_if(el, detail::target_is<vertex_descriptor>(v));
       
   104     }
       
   105     // O(log(E/V))
       
   106     template <class EdgeList, class vertex_descriptor>
       
   107     void erase_from_incidence_list(EdgeList& el, vertex_descriptor v,
       
   108                                    disallow_parallel_edge_tag)
       
   109     {
       
   110       typedef typename EdgeList::value_type StoredEdge;
       
   111       el.erase(StoredEdge(v));
       
   112     }
       
   113 
       
   114     //=========================================================================
       
   115     // Out-Edge and In-Edge Iterator Implementation
       
   116 
       
   117     template <class BaseIter, class VertexDescriptor, class EdgeDescriptor, class Difference>
       
   118     struct out_edge_iter
       
   119       : iterator_adaptor<
       
   120             out_edge_iter<BaseIter, VertexDescriptor, EdgeDescriptor, Difference>
       
   121           , BaseIter
       
   122           , EdgeDescriptor
       
   123           , use_default
       
   124           , EdgeDescriptor
       
   125           , Difference
       
   126         >
       
   127     {
       
   128       typedef iterator_adaptor<
       
   129           out_edge_iter<BaseIter, VertexDescriptor, EdgeDescriptor, Difference>
       
   130         , BaseIter
       
   131         , EdgeDescriptor
       
   132         , use_default
       
   133         , EdgeDescriptor
       
   134         , Difference
       
   135       > super_t;
       
   136         
       
   137       inline out_edge_iter() { }
       
   138         inline out_edge_iter(const BaseIter& i, const VertexDescriptor& src)
       
   139           : super_t(i), m_src(src) { }
       
   140 
       
   141       inline EdgeDescriptor
       
   142       dereference() const
       
   143       {
       
   144         return EdgeDescriptor(m_src, (*this->base()).get_target(), 
       
   145                               &(*this->base()).get_property());
       
   146       }
       
   147       VertexDescriptor m_src;
       
   148     };
       
   149   
       
   150     template <class BaseIter, class VertexDescriptor, class EdgeDescriptor, class Difference>
       
   151     struct in_edge_iter
       
   152       : iterator_adaptor<
       
   153             in_edge_iter<BaseIter, VertexDescriptor, EdgeDescriptor, Difference>
       
   154           , BaseIter
       
   155           , EdgeDescriptor
       
   156           , use_default
       
   157           , EdgeDescriptor
       
   158           , Difference
       
   159         >
       
   160     {
       
   161       typedef iterator_adaptor<
       
   162           in_edge_iter<BaseIter, VertexDescriptor, EdgeDescriptor, Difference>
       
   163         , BaseIter
       
   164         , EdgeDescriptor
       
   165         , use_default
       
   166         , EdgeDescriptor
       
   167         , Difference
       
   168       > super_t;
       
   169         
       
   170       inline in_edge_iter() { }
       
   171       inline in_edge_iter(const BaseIter& i, const VertexDescriptor& src) 
       
   172         : super_t(i), m_src(src) { }
       
   173 
       
   174       inline EdgeDescriptor
       
   175       dereference() const
       
   176       {
       
   177         return EdgeDescriptor((*this->base()).get_target(), m_src,
       
   178                               &this->base()->get_property());
       
   179       }
       
   180       VertexDescriptor m_src;
       
   181     };
       
   182 
       
   183     //=========================================================================
       
   184     // Undirected Edge Iterator Implementation
       
   185 
       
   186     template <class EdgeIter, class EdgeDescriptor, class Difference>
       
   187     struct undirected_edge_iter
       
   188       : iterator_adaptor<
       
   189             undirected_edge_iter<EdgeIter, EdgeDescriptor, Difference>
       
   190           , EdgeIter
       
   191           , EdgeDescriptor
       
   192           , use_default
       
   193           , EdgeDescriptor
       
   194           , Difference
       
   195         >
       
   196     {
       
   197       typedef iterator_adaptor<
       
   198           undirected_edge_iter<EdgeIter, EdgeDescriptor, Difference>
       
   199         , EdgeIter
       
   200         , EdgeDescriptor
       
   201         , use_default
       
   202         , EdgeDescriptor
       
   203         , Difference
       
   204       > super_t;
       
   205 
       
   206       undirected_edge_iter() {}
       
   207         
       
   208       explicit undirected_edge_iter(EdgeIter i)
       
   209           : super_t(i) {}
       
   210         
       
   211       inline EdgeDescriptor
       
   212       dereference() const {
       
   213         return EdgeDescriptor(
       
   214             (*this->base()).m_source
       
   215           , (*this->base()).m_target
       
   216           , &this->base()->get_property());
       
   217       }
       
   218     };
       
   219 
       
   220     //=========================================================================
       
   221     // Edge Storage Types (stored in the out-edge/in-edge lists)
       
   222 
       
   223     template <class Vertex>
       
   224     class stored_edge
       
   225       : public boost::equality_comparable1< stored_edge<Vertex>,
       
   226         boost::less_than_comparable1< stored_edge<Vertex> > >
       
   227     {
       
   228     public:
       
   229       typedef no_property property_type;
       
   230       inline stored_edge() { }
       
   231       inline stored_edge(Vertex target, const no_property& = no_property())
       
   232         : m_target(target) { }
       
   233       // Need to write this explicitly so stored_edge_property can
       
   234       // invoke Base::operator= (at least, for SGI MIPSPro compiler)
       
   235       inline stored_edge& operator=(const stored_edge& x) {
       
   236         m_target = x.m_target;
       
   237         return *this;
       
   238       }
       
   239       inline Vertex& get_target() const { return m_target; }
       
   240       inline const no_property& get_property() const { return s_prop; }
       
   241       inline bool operator==(const stored_edge& x) const
       
   242         { return m_target == x.get_target(); }
       
   243       inline bool operator<(const stored_edge& x) const
       
   244         { return m_target < x.get_target(); }
       
   245       //protected: need to add hash<> as a friend
       
   246       static no_property s_prop;
       
   247       // Sometimes target not used as key in the set, and in that case
       
   248       // it is ok to change the target.
       
   249       mutable Vertex m_target;
       
   250     };
       
   251     template <class Vertex>
       
   252     no_property stored_edge<Vertex>::s_prop;
       
   253 
       
   254     template <class Vertex, class Property>
       
   255     class stored_edge_property : public stored_edge<Vertex> {
       
   256       typedef stored_edge_property self;
       
   257       typedef stored_edge<Vertex> Base;
       
   258     public:
       
   259       typedef Property property_type;
       
   260       inline stored_edge_property() { }
       
   261       inline stored_edge_property(Vertex target,
       
   262                                   const Property& p = Property())
       
   263         : stored_edge<Vertex>(target), m_property(new Property(p)) { }
       
   264       stored_edge_property(const self& x) 
       
   265         : Base(x), m_property(const_cast<self&>(x).m_property) { }
       
   266       self& operator=(const self& x) {
       
   267         Base::operator=(x);
       
   268         m_property = const_cast<self&>(x).m_property; 
       
   269         return *this;
       
   270       }
       
   271       inline Property& get_property() { return *m_property; }
       
   272       inline const Property& get_property() const { return *m_property; }
       
   273     protected:
       
   274       // Holding the property by-value causes edge-descriptor
       
   275       // invalidation for add_edge() with EdgeList=vecS. Instead we
       
   276       // hold a pointer to the property. std::auto_ptr is not
       
   277       // a perfect fit for the job, but it is darn close.
       
   278       std::auto_ptr<Property> m_property;
       
   279     };
       
   280 
       
   281 
       
   282     template <class Vertex, class Iter, class Property>
       
   283     class stored_edge_iter
       
   284       : public stored_edge<Vertex>
       
   285     {
       
   286     public:
       
   287       typedef Property property_type;
       
   288       inline stored_edge_iter() { }
       
   289       inline stored_edge_iter(Vertex v)
       
   290         : stored_edge<Vertex>(v) { }
       
   291       inline stored_edge_iter(Vertex v, Iter i, void* = 0)
       
   292         : stored_edge<Vertex>(v), m_iter(i) { }
       
   293       inline Property& get_property() { return m_iter->get_property(); }
       
   294       inline const Property& get_property() const { 
       
   295         return m_iter->get_property();
       
   296       }
       
   297       inline Iter get_iter() const { return m_iter; }
       
   298     protected:
       
   299       Iter m_iter;
       
   300     };
       
   301 
       
   302     // For when the EdgeList is a std::vector.
       
   303     // Want to make the iterator stable, so use an offset
       
   304     // instead of an iterator into a std::vector
       
   305     template <class Vertex, class EdgeVec, class Property>
       
   306     class stored_ra_edge_iter
       
   307       : public stored_edge<Vertex>
       
   308     {
       
   309       typedef typename EdgeVec::iterator Iter;
       
   310     public:
       
   311       typedef Property property_type;
       
   312       inline stored_ra_edge_iter() { }
       
   313       inline stored_ra_edge_iter(Vertex v, Iter i = Iter(), 
       
   314                                  EdgeVec* edge_vec = 0)
       
   315         : stored_edge<Vertex>(v), m_i(i - edge_vec->begin()), m_vec(edge_vec){ }
       
   316       inline Property& get_property() { return (*m_vec)[m_i].get_property(); }
       
   317       inline const Property& get_property() const { 
       
   318         return (*m_vec)[m_i].get_property();
       
   319       }
       
   320       inline Iter get_iter() const { return m_vec->begin() + m_i; }
       
   321     protected:
       
   322       std::size_t m_i;
       
   323       EdgeVec* m_vec;
       
   324     };
       
   325 
       
   326   } // namespace detail
       
   327     
       
   328   template <class Tag, class Vertex, class Property>
       
   329   const typename property_value<Property,Tag>::type&
       
   330   get(Tag property_tag,
       
   331       const detail::stored_edge_property<Vertex, Property>& e)
       
   332   {
       
   333     return get_property_value(e.get_property(), property_tag);
       
   334   }
       
   335 
       
   336   template <class Tag, class Vertex, class Iter, class Property>
       
   337   const typename property_value<Property,Tag>::type&
       
   338   get(Tag property_tag,
       
   339       const detail::stored_edge_iter<Vertex, Iter, Property>& e)
       
   340   {
       
   341     return get_property_value(e.get_property(), property_tag);
       
   342   }
       
   343 
       
   344   template <class Tag, class Vertex, class EdgeVec, class Property>
       
   345   const typename property_value<Property,Tag>::type&
       
   346   get(Tag property_tag,
       
   347       const detail::stored_ra_edge_iter<Vertex, EdgeVec, Property>& e)
       
   348   {
       
   349     return get_property_value(e.get_property(), property_tag);
       
   350   }
       
   351     
       
   352     //=========================================================================
       
   353     // Directed Edges Helper Class
       
   354 
       
   355     namespace detail {
       
   356 
       
   357       // O(E/V)
       
   358       template <class edge_descriptor, class EdgeList, class StoredProperty>
       
   359       inline void
       
   360       remove_directed_edge_dispatch(edge_descriptor, EdgeList& el,
       
   361                                     StoredProperty& p)
       
   362       {
       
   363         for (typename EdgeList::iterator i = el.begin();
       
   364              i != el.end(); ++i)
       
   365           if (&(*i).get_property() == &p) {
       
   366             el.erase(i);
       
   367             return;
       
   368           }
       
   369       }
       
   370 
       
   371       template <class incidence_iterator, class EdgeList, class Predicate>
       
   372       inline void
       
   373       remove_directed_edge_if_dispatch(incidence_iterator first,
       
   374                                        incidence_iterator last, 
       
   375                                        EdgeList& el, Predicate pred,
       
   376                                        boost::allow_parallel_edge_tag)
       
   377       {
       
   378         // remove_if
       
   379         while (first != last && !pred(*first))
       
   380           ++first;
       
   381         incidence_iterator i = first;
       
   382         if (first != last)
       
   383           for (; i != last; ++i)
       
   384             if (!pred(*i)) {
       
   385               *first.base() = *i.base();
       
   386               ++first;
       
   387             }
       
   388         el.erase(first.base(), el.end());
       
   389       }
       
   390       template <class incidence_iterator, class EdgeList, class Predicate>
       
   391       inline void
       
   392       remove_directed_edge_if_dispatch(incidence_iterator first,
       
   393                                        incidence_iterator last, 
       
   394                                        EdgeList& el, 
       
   395                                        Predicate pred,
       
   396                                        boost::disallow_parallel_edge_tag)
       
   397       {
       
   398         for (incidence_iterator next = first;
       
   399              first != last; first = next) {
       
   400           ++next;
       
   401           if (pred(*first))
       
   402             el.erase( first.base() );
       
   403         }
       
   404       }
       
   405 
       
   406       template <class PropT, class Graph, class incidence_iterator, 
       
   407                 class EdgeList, class Predicate>
       
   408       inline void
       
   409       undirected_remove_out_edge_if_dispatch(Graph& g, 
       
   410                                              incidence_iterator first,
       
   411                                              incidence_iterator last, 
       
   412                                              EdgeList& el, Predicate pred,
       
   413                                              boost::allow_parallel_edge_tag)
       
   414       {
       
   415         typedef typename Graph::global_edgelist_selector EdgeListS;
       
   416         BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
       
   417 
       
   418         // remove_if
       
   419         while (first != last && !pred(*first))
       
   420           ++first;
       
   421         incidence_iterator i = first;
       
   422         bool self_loop_removed = false;
       
   423         if (first != last)
       
   424           for (; i != last; ++i) {
       
   425             if (self_loop_removed) {
       
   426               /* With self loops, the descriptor will show up
       
   427                * twice. The first time it will be removed, and now it
       
   428                * will be skipped.
       
   429                */
       
   430               self_loop_removed = false;
       
   431             }
       
   432             else if (!pred(*i)) {
       
   433               *first.base() = *i.base();
       
   434               ++first;
       
   435             } else {
       
   436               if (source(*i, g) == target(*i, g)) self_loop_removed = true;
       
   437               else {
       
   438                 // Remove the edge from the target
       
   439                 detail::remove_directed_edge_dispatch
       
   440                   (*i, 
       
   441                    g.out_edge_list(target(*i, g)), 
       
   442                    *(PropT*)(*i).get_property());
       
   443               }
       
   444 
       
   445               // Erase the edge property
       
   446               g.m_edges.erase( (*i.base()).get_iter() );
       
   447             }
       
   448           }
       
   449         el.erase(first.base(), el.end());
       
   450       }
       
   451       template <class PropT, class Graph, class incidence_iterator, 
       
   452                 class EdgeList, class Predicate>
       
   453       inline void
       
   454       undirected_remove_out_edge_if_dispatch(Graph& g, 
       
   455                                              incidence_iterator first,
       
   456                                              incidence_iterator last, 
       
   457                                              EdgeList& el, 
       
   458                                              Predicate pred,
       
   459                                              boost::disallow_parallel_edge_tag)
       
   460       {
       
   461         typedef typename Graph::global_edgelist_selector EdgeListS;
       
   462         BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
       
   463 
       
   464         for (incidence_iterator next = first;
       
   465              first != last; first = next) {
       
   466           ++next;
       
   467           if (pred(*first)) {
       
   468             if (source(*first, g) != target(*first, g)) {
       
   469               // Remove the edge from the target
       
   470               detail::remove_directed_edge_dispatch
       
   471                 (*first, 
       
   472                  g.out_edge_list(target(*first, g)), 
       
   473                  *(PropT*)(*first).get_property());
       
   474             }
       
   475 
       
   476             // Erase the edge property
       
   477             g.m_edges.erase( (*first.base()).get_iter() );
       
   478 
       
   479             // Erase the edge in the source
       
   480             el.erase( first.base() );
       
   481           }
       
   482         }
       
   483       }
       
   484 
       
   485       // O(E/V)
       
   486       template <class edge_descriptor, class EdgeList, class StoredProperty>
       
   487       inline void
       
   488       remove_directed_edge_dispatch(edge_descriptor e, EdgeList& el,
       
   489                                     no_property&)
       
   490       {
       
   491         for (typename EdgeList::iterator i = el.begin();
       
   492              i != el.end(); ++i)
       
   493           if ((*i).get_target() == e.m_target) {
       
   494             el.erase(i);
       
   495             return;
       
   496           }
       
   497       }
       
   498 
       
   499     } // namespace detail
       
   500 
       
   501     template <class Config>
       
   502     struct directed_edges_helper {
       
   503 
       
   504       // Placement of these overloaded remove_edge() functions
       
   505       // inside the class avoids a VC++ bug.
       
   506       
       
   507       // O(E/V)
       
   508       inline void
       
   509       remove_edge(typename Config::edge_descriptor e)
       
   510       {
       
   511         typedef typename Config::graph_type graph_type;
       
   512         graph_type& g = static_cast<graph_type&>(*this);
       
   513         typename Config::OutEdgeList& el = g.out_edge_list(source(e, g));
       
   514         typedef typename Config::OutEdgeList::value_type::property_type PType;
       
   515         detail::remove_directed_edge_dispatch(e, el,
       
   516                                               *(PType*)e.get_property());
       
   517       }
       
   518 
       
   519       // O(1)
       
   520       inline void
       
   521       remove_edge(typename Config::out_edge_iterator iter)
       
   522       {
       
   523         typedef typename Config::graph_type graph_type;
       
   524         graph_type& g = static_cast<graph_type&>(*this);
       
   525         typename Config::edge_descriptor e = *iter;
       
   526         typename Config::OutEdgeList& el = g.out_edge_list(source(e, g));
       
   527         el.erase(iter.base());
       
   528       }
       
   529 
       
   530     };
       
   531 
       
   532     // O(1)
       
   533     template <class Config>
       
   534     inline std::pair<typename Config::edge_iterator, 
       
   535                      typename Config::edge_iterator>
       
   536     edges(const directed_edges_helper<Config>& g_)
       
   537     {
       
   538       typedef typename Config::graph_type graph_type;
       
   539       typedef typename Config::edge_iterator edge_iterator;
       
   540       const graph_type& cg = static_cast<const graph_type&>(g_);
       
   541       graph_type& g = const_cast<graph_type&>(cg);
       
   542       return std::make_pair( edge_iterator(g.vertex_set().begin(), 
       
   543                                            g.vertex_set().begin(), 
       
   544                                            g.vertex_set().end(), g),
       
   545                              edge_iterator(g.vertex_set().begin(),
       
   546                                            g.vertex_set().end(),
       
   547                                            g.vertex_set().end(), g) );
       
   548     }
       
   549 
       
   550     //=========================================================================
       
   551     // Directed Graph Helper Class
       
   552 
       
   553     struct adj_list_dir_traversal_tag :
       
   554       public virtual vertex_list_graph_tag,
       
   555       public virtual incidence_graph_tag,
       
   556       public virtual adjacency_graph_tag,
       
   557       public virtual edge_list_graph_tag { };
       
   558 
       
   559     template <class Config>
       
   560     struct directed_graph_helper
       
   561       : public directed_edges_helper<Config> { 
       
   562       typedef typename Config::edge_descriptor edge_descriptor;
       
   563       typedef adj_list_dir_traversal_tag traversal_category;
       
   564     };
       
   565 
       
   566     // O(E/V)
       
   567     template <class Config>
       
   568     inline void
       
   569     remove_edge(typename Config::vertex_descriptor u,
       
   570                 typename Config::vertex_descriptor v,
       
   571                 directed_graph_helper<Config>& g_)
       
   572     {
       
   573       typedef typename Config::graph_type graph_type;
       
   574       typedef typename Config::edge_parallel_category Cat;
       
   575       graph_type& g = static_cast<graph_type&>(g_);
       
   576       detail::erase_from_incidence_list(g.out_edge_list(u), v, Cat());
       
   577     }
       
   578 
       
   579     template <class Config, class Predicate>
       
   580     inline void
       
   581     remove_out_edge_if(typename Config::vertex_descriptor u, Predicate pred,
       
   582                        directed_graph_helper<Config>& g_)
       
   583     {
       
   584       typedef typename Config::graph_type graph_type;
       
   585       graph_type& g = static_cast<graph_type&>(g_);
       
   586       typename Config::out_edge_iterator first, last;
       
   587       tie(first, last) = out_edges(u, g);
       
   588       typedef typename Config::edge_parallel_category edge_parallel_category;
       
   589       detail::remove_directed_edge_if_dispatch
       
   590         (first, last, g.out_edge_list(u), pred, edge_parallel_category());
       
   591     }
       
   592 
       
   593     template <class Config, class Predicate>
       
   594     inline void
       
   595     remove_edge_if(Predicate pred, directed_graph_helper<Config>& g_)
       
   596     {
       
   597       typedef typename Config::graph_type graph_type;
       
   598       graph_type& g = static_cast<graph_type&>(g_);
       
   599 
       
   600       typename Config::vertex_iterator vi, vi_end;
       
   601       for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
       
   602         remove_out_edge_if(*vi, pred, g);
       
   603     }    
       
   604 
       
   605     template <class EdgeOrIter, class Config>
       
   606     inline void
       
   607     remove_edge(EdgeOrIter e_or_iter, directed_graph_helper<Config>& g_)
       
   608     {
       
   609       g_.remove_edge(e_or_iter);
       
   610     }
       
   611 
       
   612     // O(V + E) for allow_parallel_edges
       
   613     // O(V * log(E/V)) for disallow_parallel_edges
       
   614     template <class Config>
       
   615     inline void 
       
   616     clear_vertex(typename Config::vertex_descriptor u,
       
   617                  directed_graph_helper<Config>& g_)
       
   618     {
       
   619       typedef typename Config::graph_type graph_type;
       
   620       typedef typename Config::edge_parallel_category Cat;
       
   621       graph_type& g = static_cast<graph_type&>(g_);
       
   622       typename Config::vertex_iterator vi, viend;
       
   623       for (boost::tie(vi, viend) = vertices(g); vi != viend; ++vi)
       
   624         detail::erase_from_incidence_list(g.out_edge_list(*vi), u, Cat());
       
   625       g.out_edge_list(u).clear();
       
   626       // clear() should be a req of Sequence and AssociativeContainer,
       
   627       // or maybe just Container
       
   628     }
       
   629 
       
   630     template <class Config>
       
   631     inline void 
       
   632     clear_out_edges(typename Config::vertex_descriptor u,
       
   633                     directed_graph_helper<Config>& g_)
       
   634     {
       
   635       typedef typename Config::graph_type graph_type;
       
   636       typedef typename Config::edge_parallel_category Cat;
       
   637       graph_type& g = static_cast<graph_type&>(g_);
       
   638       g.out_edge_list(u).clear();
       
   639       // clear() should be a req of Sequence and AssociativeContainer,
       
   640       // or maybe just Container
       
   641     }
       
   642 
       
   643     // O(V), could do better...
       
   644     template <class Config>
       
   645     inline typename Config::edges_size_type
       
   646     num_edges(const directed_graph_helper<Config>& g_)
       
   647     {
       
   648       typedef typename Config::graph_type graph_type;
       
   649       const graph_type& g = static_cast<const graph_type&>(g_);
       
   650       typename Config::edges_size_type num_e = 0;
       
   651       typename Config::vertex_iterator vi, vi_end;
       
   652       for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
       
   653         num_e += out_degree(*vi, g);
       
   654       return num_e;
       
   655     }
       
   656     // O(1) for allow_parallel_edge_tag
       
   657     // O(log(E/V)) for disallow_parallel_edge_tag
       
   658     template <class Config>
       
   659     inline std::pair<typename directed_graph_helper<Config>::edge_descriptor, bool>
       
   660     add_edge(typename Config::vertex_descriptor u, 
       
   661              typename Config::vertex_descriptor v,
       
   662              const typename Config::edge_property_type& p, 
       
   663              directed_graph_helper<Config>& g_)
       
   664     {
       
   665       typedef typename Config::edge_descriptor edge_descriptor;
       
   666       typedef typename Config::graph_type graph_type;
       
   667       typedef typename Config::StoredEdge StoredEdge;
       
   668       graph_type& g = static_cast<graph_type&>(g_);
       
   669       typename Config::OutEdgeList::iterator i; 
       
   670       bool inserted;
       
   671       boost::tie(i, inserted) = boost::graph_detail::push(g.out_edge_list(u), 
       
   672                                             StoredEdge(v, p));
       
   673       return std::make_pair(edge_descriptor(u, v, &(*i).get_property()), 
       
   674                             inserted);
       
   675     }
       
   676     // Did not use default argument here because that
       
   677     // causes Visual C++ to get confused.
       
   678     template <class Config>
       
   679     inline std::pair<typename Config::edge_descriptor, bool>
       
   680     add_edge(typename Config::vertex_descriptor u, 
       
   681              typename Config::vertex_descriptor v,
       
   682              directed_graph_helper<Config>& g_)
       
   683     {
       
   684       typename Config::edge_property_type p;
       
   685       return add_edge(u, v, p, g_);
       
   686     }
       
   687     //=========================================================================
       
   688     // Undirected Graph Helper Class
       
   689 
       
   690     template <class Config>
       
   691     struct undirected_graph_helper;
       
   692 
       
   693     struct undir_adj_list_traversal_tag : 
       
   694       public virtual vertex_list_graph_tag,
       
   695       public virtual incidence_graph_tag,
       
   696       public virtual adjacency_graph_tag,
       
   697       public virtual edge_list_graph_tag,
       
   698       public virtual bidirectional_graph_tag { };
       
   699 
       
   700     namespace detail {
       
   701 
       
   702       // using class with specialization for dispatch is a VC++ workaround.
       
   703       template <class StoredProperty>
       
   704       struct remove_undirected_edge_dispatch {
       
   705 
       
   706         // O(E/V)
       
   707         template <class edge_descriptor, class Config>
       
   708         static void
       
   709         apply(edge_descriptor e, 
       
   710               undirected_graph_helper<Config>& g_, 
       
   711               StoredProperty& p)
       
   712         {
       
   713           typedef typename Config::global_edgelist_selector EdgeListS;
       
   714           BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
       
   715 
       
   716           typedef typename Config::graph_type graph_type;
       
   717           graph_type& g = static_cast<graph_type&>(g_);
       
   718           
       
   719           typename Config::OutEdgeList& out_el = g.out_edge_list(source(e, g));
       
   720           typename Config::OutEdgeList::iterator out_i = out_el.begin();
       
   721           for (; out_i != out_el.end(); ++out_i)
       
   722             if (&(*out_i).get_property() == &p) {
       
   723               out_el.erase(out_i);
       
   724               break;
       
   725             }
       
   726           typename Config::OutEdgeList& in_el = g.out_edge_list(target(e, g));
       
   727           typename Config::OutEdgeList::iterator in_i = in_el.begin();
       
   728           for (; in_i != in_el.end(); ++in_i)
       
   729             if (&(*in_i).get_property() == &p) {
       
   730               g.m_edges.erase((*in_i).get_iter());
       
   731               in_el.erase(in_i);
       
   732               return;
       
   733             }
       
   734         }
       
   735       };
       
   736 
       
   737       template <>
       
   738       struct remove_undirected_edge_dispatch<no_property> {
       
   739         // O(E/V)
       
   740         template <class edge_descriptor, class Config>
       
   741         static void
       
   742         apply(edge_descriptor e,
       
   743               undirected_graph_helper<Config>& g_,
       
   744               no_property&)
       
   745         {
       
   746           typedef typename Config::global_edgelist_selector EdgeListS;
       
   747           BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
       
   748 
       
   749           typedef typename Config::graph_type graph_type;
       
   750           graph_type& g = static_cast<graph_type&>(g_);
       
   751           no_property* p = (no_property*)e.get_property();
       
   752           typename Config::OutEdgeList& out_el = g.out_edge_list(source(e, g));
       
   753           typename Config::OutEdgeList::iterator out_i = out_el.begin();
       
   754           for (; out_i != out_el.end(); ++out_i)
       
   755             if (&(*out_i).get_property() == p) {
       
   756               out_el.erase(out_i);
       
   757               break;
       
   758             }
       
   759           typename Config::OutEdgeList& in_el = g.out_edge_list(target(e, g));
       
   760           typename Config::OutEdgeList::iterator in_i = in_el.begin();
       
   761           for (; in_i != in_el.end(); ++in_i)
       
   762             if (&(*in_i).get_property() == p) {
       
   763               g.m_edges.erase((*in_i).get_iter());
       
   764               in_el.erase(in_i);
       
   765               return;
       
   766             }
       
   767         }
       
   768       };
       
   769 
       
   770       // O(E/V)
       
   771       template <class Graph, class EdgeList, class Vertex>
       
   772       inline void
       
   773       remove_edge_and_property(Graph& g, EdgeList& el, Vertex v, 
       
   774                                boost::allow_parallel_edge_tag cat)
       
   775       {
       
   776         typedef typename Graph::global_edgelist_selector EdgeListS;
       
   777         BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
       
   778 
       
   779         typedef typename EdgeList::value_type StoredEdge;
       
   780         typename EdgeList::iterator i = el.begin(), end = el.end();
       
   781         for (; i != end; ++i)
       
   782           if ((*i).get_target() == v)
       
   783             g.m_edges.erase((*i).get_iter());
       
   784         detail::erase_from_incidence_list(el, v, cat);
       
   785       }
       
   786       // O(log(E/V))
       
   787       template <class Graph, class EdgeList, class Vertex>
       
   788       inline void
       
   789       remove_edge_and_property(Graph& g, EdgeList& el, Vertex v, 
       
   790                                boost::disallow_parallel_edge_tag)
       
   791       {
       
   792         typedef typename Graph::global_edgelist_selector EdgeListS;
       
   793         BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
       
   794 
       
   795         typedef typename EdgeList::value_type StoredEdge;
       
   796         typename EdgeList::iterator i = el.find(StoredEdge(v)), end = el.end();
       
   797         if (i != end) {
       
   798           g.m_edges.erase((*i).get_iter());
       
   799           el.erase(i);
       
   800         }
       
   801       }
       
   802 
       
   803     } // namespace detail
       
   804 
       
   805     template <class Vertex, class EdgeProperty>
       
   806     struct list_edge // short name due to VC++ truncation and linker problems
       
   807       : public boost::detail::edge_base<boost::undirected_tag, Vertex>
       
   808     {
       
   809       typedef EdgeProperty property_type;
       
   810       typedef boost::detail::edge_base<boost::undirected_tag, Vertex> Base;
       
   811       list_edge(Vertex u, Vertex v, const EdgeProperty& p = EdgeProperty())
       
   812         : Base(u, v), m_property(p) { }
       
   813       EdgeProperty& get_property() { return m_property; }
       
   814       const EdgeProperty& get_property() const { return m_property; }
       
   815       // the following methods should never be used, but are needed
       
   816       // to make SGI MIPSpro C++ happy
       
   817       list_edge() { }
       
   818       bool operator==(const list_edge&) const { return false; }
       
   819       bool operator<(const list_edge&) const { return false; }
       
   820       EdgeProperty m_property;
       
   821     };
       
   822 
       
   823     template <class Config>
       
   824     struct undirected_graph_helper {
       
   825 
       
   826       typedef undir_adj_list_traversal_tag traversal_category;
       
   827 
       
   828       // Placement of these overloaded remove_edge() functions
       
   829       // inside the class avoids a VC++ bug.
       
   830 
       
   831       // O(E/V)
       
   832       inline void
       
   833       remove_edge(typename Config::edge_descriptor e)
       
   834       {
       
   835         typedef typename Config::global_edgelist_selector EdgeListS;
       
   836         BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
       
   837 
       
   838         typedef typename Config::OutEdgeList::value_type::property_type PType;
       
   839         detail::remove_undirected_edge_dispatch<PType>::apply
       
   840           (e, *this, *(PType*)e.get_property());
       
   841       }
       
   842       // O(E/V)
       
   843       inline void
       
   844       remove_edge(typename Config::out_edge_iterator iter)
       
   845       {
       
   846         this->remove_edge(*iter);
       
   847       }
       
   848     };
       
   849 
       
   850     // Had to make these non-members to avoid accidental instantiation
       
   851     // on SGI MIPSpro C++
       
   852     template <class C>
       
   853     inline typename C::InEdgeList& 
       
   854     in_edge_list(undirected_graph_helper<C>&, 
       
   855                  typename C::vertex_descriptor v)
       
   856     {
       
   857       typename C::stored_vertex* sv = (typename C::stored_vertex*)v;
       
   858       return sv->m_out_edges;
       
   859     }
       
   860     template <class C>
       
   861     inline const typename C::InEdgeList& 
       
   862     in_edge_list(const undirected_graph_helper<C>&,
       
   863                  typename C::vertex_descriptor v) {
       
   864       typename C::stored_vertex* sv = (typename C::stored_vertex*)v;
       
   865       return sv->m_out_edges;
       
   866     }
       
   867 
       
   868     // O(E/V)
       
   869     template <class EdgeOrIter, class Config>
       
   870     inline void
       
   871     remove_edge(EdgeOrIter e, undirected_graph_helper<Config>& g_)
       
   872     {
       
   873       typedef typename Config::global_edgelist_selector EdgeListS;
       
   874       BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
       
   875 
       
   876       g_.remove_edge(e);
       
   877     }
       
   878 
       
   879     // O(E/V) or O(log(E/V))
       
   880     template <class Config>
       
   881     void
       
   882     remove_edge(typename Config::vertex_descriptor u, 
       
   883                 typename Config::vertex_descriptor v, 
       
   884                 undirected_graph_helper<Config>& g_)
       
   885     {
       
   886       typedef typename Config::global_edgelist_selector EdgeListS;
       
   887       BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
       
   888 
       
   889       typedef typename Config::graph_type graph_type;
       
   890       graph_type& g = static_cast<graph_type&>(g_);
       
   891       typedef typename Config::edge_parallel_category Cat;
       
   892       detail::remove_edge_and_property(g, g.out_edge_list(u), v, Cat());
       
   893       detail::erase_from_incidence_list(g.out_edge_list(v), u, Cat());
       
   894     }
       
   895   
       
   896     template <class Config, class Predicate>
       
   897     void
       
   898     remove_out_edge_if(typename Config::vertex_descriptor u, Predicate pred,
       
   899                        undirected_graph_helper<Config>& g_)
       
   900     {
       
   901       typedef typename Config::global_edgelist_selector EdgeListS;
       
   902       BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
       
   903         
       
   904       typedef typename Config::graph_type graph_type;
       
   905       typedef typename Config::OutEdgeList::value_type::property_type PropT;
       
   906       graph_type& g = static_cast<graph_type&>(g_);
       
   907       typename Config::out_edge_iterator first, last;
       
   908       tie(first, last) = out_edges(u, g);
       
   909       typedef typename Config::edge_parallel_category Cat;
       
   910       detail::undirected_remove_out_edge_if_dispatch<PropT>
       
   911         (g, first, last, g.out_edge_list(u), pred, Cat());
       
   912     }
       
   913     template <class Config, class Predicate>
       
   914     void
       
   915     remove_in_edge_if(typename Config::vertex_descriptor u, Predicate pred,
       
   916                       undirected_graph_helper<Config>& g_)
       
   917     {
       
   918       typedef typename Config::global_edgelist_selector EdgeListS;
       
   919       BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
       
   920 
       
   921       remove_out_edge_if(u, pred, g_);
       
   922     }
       
   923 
       
   924     // O(E/V * E) or O(log(E/V) * E)
       
   925     template <class Predicate, class Config>
       
   926     void
       
   927     remove_edge_if(Predicate pred, undirected_graph_helper<Config>& g_)
       
   928     {
       
   929       typedef typename Config::global_edgelist_selector EdgeListS;
       
   930       BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
       
   931 
       
   932       typedef typename Config::graph_type graph_type;
       
   933       graph_type& g = static_cast<graph_type&>(g_);
       
   934       typename Config::edge_iterator ei, ei_end, next;
       
   935       tie(ei, ei_end) = edges(g);
       
   936       for (next = ei; ei != ei_end; ei = next) {
       
   937         ++next;
       
   938         if (pred(*ei))
       
   939           remove_edge(*ei, g);
       
   940       }
       
   941     }
       
   942 
       
   943     // O(1)
       
   944     template <class Config>
       
   945     inline std::pair<typename Config::edge_iterator, 
       
   946                      typename Config::edge_iterator>
       
   947     edges(const undirected_graph_helper<Config>& g_)
       
   948     {
       
   949       typedef typename Config::graph_type graph_type;
       
   950       typedef typename Config::edge_iterator edge_iterator;
       
   951       const graph_type& cg = static_cast<const graph_type&>(g_);
       
   952       graph_type& g = const_cast<graph_type&>(cg);
       
   953       return std::make_pair( edge_iterator(g.m_edges.begin()),
       
   954                              edge_iterator(g.m_edges.end()) );
       
   955     }
       
   956     // O(1)
       
   957     template <class Config>
       
   958     inline typename Config::edges_size_type
       
   959     num_edges(const undirected_graph_helper<Config>& g_) 
       
   960     {
       
   961       typedef typename Config::graph_type graph_type;
       
   962       const graph_type& g = static_cast<const graph_type&>(g_);
       
   963       return g.m_edges.size();
       
   964     }
       
   965     // O(E/V * E/V)
       
   966     template <class Config>
       
   967     inline void 
       
   968     clear_vertex(typename Config::vertex_descriptor u,
       
   969                  undirected_graph_helper<Config>& g_)
       
   970     {
       
   971       typedef typename Config::global_edgelist_selector EdgeListS;
       
   972       BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
       
   973 
       
   974       typedef typename Config::graph_type graph_type;
       
   975       typedef typename Config::edge_parallel_category Cat;
       
   976       graph_type& g = static_cast<graph_type&>(g_);
       
   977       typename Config::OutEdgeList& el = g.out_edge_list(u);
       
   978       typename Config::OutEdgeList::iterator 
       
   979         ei = el.begin(), ei_end = el.end();
       
   980       for (; ei != ei_end; ++ei) {
       
   981         detail::erase_from_incidence_list
       
   982           (g.out_edge_list((*ei).get_target()), u, Cat());
       
   983         g.m_edges.erase((*ei).get_iter());
       
   984       }
       
   985       g.out_edge_list(u).clear();
       
   986     }
       
   987     // O(1) for allow_parallel_edge_tag
       
   988     // O(log(E/V)) for disallow_parallel_edge_tag
       
   989     template <class Config>
       
   990     inline std::pair<typename Config::edge_descriptor, bool>
       
   991     add_edge(typename Config::vertex_descriptor u, 
       
   992              typename Config::vertex_descriptor v, 
       
   993              const typename Config::edge_property_type& p,
       
   994              undirected_graph_helper<Config>& g_)
       
   995     {
       
   996       typedef typename Config::StoredEdge StoredEdge;
       
   997       typedef typename Config::edge_descriptor edge_descriptor;
       
   998       typedef typename Config::graph_type graph_type;
       
   999       graph_type& g = static_cast<graph_type&>(g_);
       
  1000 
       
  1001       bool inserted;
       
  1002       typename Config::EdgeContainer::value_type e(u, v, p);
       
  1003       typename Config::EdgeContainer::iterator p_iter 
       
  1004         = graph_detail::push(g.m_edges, e).first;
       
  1005 
       
  1006       typename Config::OutEdgeList::iterator i;
       
  1007       boost::tie(i, inserted) = boost::graph_detail::push(g.out_edge_list(u), 
       
  1008                                     StoredEdge(v, p_iter, &g.m_edges));
       
  1009       if (inserted) {
       
  1010         boost::graph_detail::push(g.out_edge_list(v), StoredEdge(u, p_iter, &g.m_edges));
       
  1011         return std::make_pair(edge_descriptor(u, v, &p_iter->get_property()),
       
  1012                               true);
       
  1013       } else {
       
  1014         g.m_edges.erase(p_iter);
       
  1015         return std::make_pair
       
  1016           (edge_descriptor(u, v, &i->get_iter()->get_property()), false);
       
  1017       }
       
  1018     }
       
  1019     template <class Config>
       
  1020     inline std::pair<typename Config::edge_descriptor, bool>
       
  1021     add_edge(typename Config::vertex_descriptor u, 
       
  1022              typename Config::vertex_descriptor v, 
       
  1023              undirected_graph_helper<Config>& g_)
       
  1024     {
       
  1025       typename Config::edge_property_type p;
       
  1026       return add_edge(u, v, p, g_);
       
  1027     }
       
  1028 
       
  1029     // O(1)
       
  1030     template <class Config>
       
  1031     inline typename Config::degree_size_type
       
  1032     degree(typename Config::vertex_descriptor u, 
       
  1033            const undirected_graph_helper<Config>& g_)
       
  1034     {
       
  1035       typedef typename Config::graph_type Graph;
       
  1036       const Graph& g = static_cast<const Graph&>(g_);
       
  1037       return out_degree(u, g);
       
  1038     }
       
  1039 
       
  1040     template <class Config>
       
  1041     inline std::pair<typename Config::in_edge_iterator, 
       
  1042                      typename Config::in_edge_iterator>
       
  1043     in_edges(typename Config::vertex_descriptor u, 
       
  1044              const undirected_graph_helper<Config>& g_)
       
  1045     {
       
  1046       typedef typename Config::graph_type Graph;
       
  1047       const Graph& cg = static_cast<const Graph&>(g_);
       
  1048       Graph& g = const_cast<Graph&>(cg);
       
  1049       typedef typename Config::in_edge_iterator in_edge_iterator;
       
  1050       return
       
  1051         std::make_pair(in_edge_iterator(g.out_edge_list(u).begin(), u),
       
  1052                        in_edge_iterator(g.out_edge_list(u).end(), u));
       
  1053     }
       
  1054 
       
  1055     template <class Config>
       
  1056     inline typename Config::degree_size_type
       
  1057     in_degree(typename Config::vertex_descriptor u,
       
  1058               const undirected_graph_helper<Config>& g_)
       
  1059     { return degree(u, g_); }
       
  1060 
       
  1061     //=========================================================================
       
  1062     // Bidirectional Graph Helper Class
       
  1063 
       
  1064     struct bidir_adj_list_traversal_tag : 
       
  1065       public virtual vertex_list_graph_tag,
       
  1066       public virtual incidence_graph_tag,
       
  1067       public virtual adjacency_graph_tag,
       
  1068       public virtual edge_list_graph_tag,
       
  1069       public virtual bidirectional_graph_tag { };
       
  1070 
       
  1071     template <class Config>
       
  1072     struct bidirectional_graph_helper
       
  1073       : public directed_edges_helper<Config> {
       
  1074       typedef bidir_adj_list_traversal_tag traversal_category;
       
  1075     };
       
  1076 
       
  1077     // Had to make these non-members to avoid accidental instantiation
       
  1078     // on SGI MIPSpro C++
       
  1079     template <class C>
       
  1080     inline typename C::InEdgeList& 
       
  1081     in_edge_list(bidirectional_graph_helper<C>&, 
       
  1082                  typename C::vertex_descriptor v)
       
  1083     {
       
  1084       typename C::stored_vertex* sv = (typename C::stored_vertex*)v;
       
  1085       return sv->m_in_edges;
       
  1086     }
       
  1087     template <class C>
       
  1088     inline const typename C::InEdgeList& 
       
  1089     in_edge_list(const bidirectional_graph_helper<C>&,
       
  1090                  typename C::vertex_descriptor v) {
       
  1091       typename C::stored_vertex* sv = (typename C::stored_vertex*)v;
       
  1092       return sv->m_in_edges;
       
  1093     }
       
  1094 
       
  1095     template <class Predicate, class Config>
       
  1096     inline void
       
  1097     remove_edge_if(Predicate pred, bidirectional_graph_helper<Config>& g_)
       
  1098     {
       
  1099       typedef typename Config::global_edgelist_selector EdgeListS;
       
  1100       BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
       
  1101 
       
  1102       typedef typename Config::graph_type graph_type;
       
  1103       graph_type& g = static_cast<graph_type&>(g_);
       
  1104       typename Config::edge_iterator ei, ei_end, next;
       
  1105       tie(ei, ei_end) = edges(g);
       
  1106       for (next = ei; ei != ei_end; ei = next) {
       
  1107         ++next;
       
  1108         if (pred(*ei))
       
  1109           remove_edge(*ei, g);
       
  1110       }
       
  1111     }
       
  1112 
       
  1113     template <class Config>
       
  1114     inline std::pair<typename Config::in_edge_iterator, 
       
  1115                      typename Config::in_edge_iterator>
       
  1116     in_edges(typename Config::vertex_descriptor u, 
       
  1117              const bidirectional_graph_helper<Config>& g_)
       
  1118     {
       
  1119       typedef typename Config::graph_type graph_type;
       
  1120       const graph_type& cg = static_cast<const graph_type&>(g_);
       
  1121       graph_type& g = const_cast<graph_type&>(cg);
       
  1122       typedef typename Config::in_edge_iterator in_edge_iterator;
       
  1123       return
       
  1124         std::make_pair(in_edge_iterator(in_edge_list(g, u).begin(), u),
       
  1125                        in_edge_iterator(in_edge_list(g, u).end(), u));
       
  1126     }
       
  1127 
       
  1128     // O(1)
       
  1129     template <class Config>
       
  1130     inline std::pair<typename Config::edge_iterator, 
       
  1131                      typename Config::edge_iterator>
       
  1132     edges(const bidirectional_graph_helper<Config>& g_)
       
  1133     {
       
  1134       typedef typename Config::graph_type graph_type;
       
  1135       typedef typename Config::edge_iterator edge_iterator;
       
  1136       const graph_type& cg = static_cast<const graph_type&>(g_);
       
  1137       graph_type& g = const_cast<graph_type&>(cg);
       
  1138       return std::make_pair( edge_iterator(g.m_edges.begin()),
       
  1139                              edge_iterator(g.m_edges.end()) );
       
  1140     }
       
  1141 
       
  1142     //=========================================================================
       
  1143     // Bidirectional Graph Helper Class (with edge properties)
       
  1144 
       
  1145 
       
  1146     template <class Config>
       
  1147     struct bidirectional_graph_helper_with_property
       
  1148       : public bidirectional_graph_helper<Config>
       
  1149     {
       
  1150       typedef typename Config::graph_type graph_type;
       
  1151       typedef typename Config::out_edge_iterator out_edge_iterator;
       
  1152       
       
  1153       std::pair<out_edge_iterator, out_edge_iterator>
       
  1154       get_parallel_edge_sublist(typename Config::edge_descriptor e,
       
  1155                                 const graph_type& g,
       
  1156                                 void*)
       
  1157       { return out_edges(source(e, g), g); }
       
  1158 
       
  1159       std::pair<out_edge_iterator, out_edge_iterator>
       
  1160       get_parallel_edge_sublist(typename Config::edge_descriptor e,
       
  1161                                 const graph_type& g,
       
  1162                                 setS*)
       
  1163       { return edge_range(source(e, g), target(e, g), g); }
       
  1164 
       
  1165       std::pair<out_edge_iterator, out_edge_iterator>
       
  1166       get_parallel_edge_sublist(typename Config::edge_descriptor e,
       
  1167                                 const graph_type& g,
       
  1168                                 multisetS*)
       
  1169       { return edge_range(source(e, g), target(e, g), g); }
       
  1170 
       
  1171 #if !defined BOOST_NO_HASH
       
  1172       std::pair<out_edge_iterator, out_edge_iterator>
       
  1173       get_parallel_edge_sublist(typename Config::edge_descriptor e,
       
  1174                                 const graph_type& g,
       
  1175                                 hash_setS*)
       
  1176       { return edge_range(source(e, g), target(e, g), g); }
       
  1177 #endif
       
  1178 
       
  1179       // Placement of these overloaded remove_edge() functions
       
  1180       // inside the class avoids a VC++ bug.
       
  1181 
       
  1182       // O(E/V) or O(log(E/V))
       
  1183       void
       
  1184       remove_edge(typename Config::edge_descriptor e)
       
  1185       {
       
  1186         typedef typename Config::global_edgelist_selector EdgeListS;
       
  1187         BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
       
  1188 
       
  1189         graph_type& g = static_cast<graph_type&>(*this);
       
  1190 
       
  1191         typedef typename Config::edgelist_selector OutEdgeListS;
       
  1192 
       
  1193         std::pair<out_edge_iterator, out_edge_iterator> rng = 
       
  1194           get_parallel_edge_sublist(e, g, (OutEdgeListS*)(0));
       
  1195         rng.first = std::find(rng.first, rng.second, e);
       
  1196         assert(rng.first != rng.second);
       
  1197         remove_edge(rng.first);
       
  1198       }
       
  1199 
       
  1200       inline void
       
  1201       remove_edge(typename Config::out_edge_iterator iter)
       
  1202       {
       
  1203         typedef typename Config::global_edgelist_selector EdgeListS;
       
  1204         BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
       
  1205 
       
  1206         typedef typename Config::graph_type graph_type;
       
  1207         graph_type& g = static_cast<graph_type&>(*this);
       
  1208         typename Config::edge_descriptor e = *iter;
       
  1209         typename Config::OutEdgeList& oel = g.out_edge_list(source(e, g));
       
  1210         typename Config::InEdgeList& iel = in_edge_list(g, target(e, g));
       
  1211         typedef typename Config::OutEdgeList::value_type::property_type PType;
       
  1212         PType& p = *(PType*)e.get_property();
       
  1213         detail::remove_directed_edge_dispatch(*iter, iel, p);
       
  1214         g.m_edges.erase(iter.base()->get_iter());
       
  1215         oel.erase(iter.base());
       
  1216       }
       
  1217     };
       
  1218 
       
  1219     // O(E/V) for allow_parallel_edge_tag
       
  1220     // O(log(E/V)) for disallow_parallel_edge_tag
       
  1221     template <class Config>
       
  1222     inline void
       
  1223     remove_edge(typename Config::vertex_descriptor u, 
       
  1224                 typename Config::vertex_descriptor v, 
       
  1225                 bidirectional_graph_helper_with_property<Config>& g_)
       
  1226     {
       
  1227       typedef typename Config::global_edgelist_selector EdgeListS;
       
  1228       BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
       
  1229 
       
  1230       typedef typename Config::graph_type graph_type;
       
  1231       graph_type& g = static_cast<graph_type&>(g_);
       
  1232       typedef typename Config::edge_parallel_category Cat;
       
  1233       detail::remove_edge_and_property(g, g.out_edge_list(u), v, Cat());
       
  1234       detail::erase_from_incidence_list(in_edge_list(g, v), u, Cat());
       
  1235     }
       
  1236 
       
  1237     // O(E/V) or O(log(E/V))
       
  1238     template <class EdgeOrIter, class Config>
       
  1239     inline void
       
  1240     remove_edge(EdgeOrIter e,
       
  1241                 bidirectional_graph_helper_with_property<Config>& g_)
       
  1242     {
       
  1243       typedef typename Config::global_edgelist_selector EdgeListS;
       
  1244       BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
       
  1245 
       
  1246       g_.remove_edge(e);
       
  1247     }
       
  1248 
       
  1249     template <class Config, class Predicate>
       
  1250     inline void
       
  1251     remove_out_edge_if(typename Config::vertex_descriptor u, Predicate pred,
       
  1252                        bidirectional_graph_helper_with_property<Config>& g_)
       
  1253     {
       
  1254       typedef typename Config::global_edgelist_selector EdgeListS;
       
  1255       BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
       
  1256 
       
  1257       typedef typename Config::graph_type graph_type;
       
  1258       typedef typename Config::OutEdgeList::value_type::property_type PropT;
       
  1259       graph_type& g = static_cast<graph_type&>(g_);
       
  1260       
       
  1261       typedef typename Config::EdgeIter EdgeIter;
       
  1262       typedef std::vector<EdgeIter> Garbage;
       
  1263       Garbage garbage;
       
  1264 
       
  1265       // First remove the edges from the targets' in-edge lists and
       
  1266       // from the graph's edge set list.
       
  1267       typename Config::out_edge_iterator out_i, out_end;
       
  1268       for (tie(out_i, out_end) = out_edges(u, g); out_i != out_end; ++out_i)
       
  1269         if (pred(*out_i)) {
       
  1270           detail::remove_directed_edge_dispatch
       
  1271             (*out_i, in_edge_list(g, target(*out_i, g)),
       
  1272              *(PropT*)(*out_i).get_property());
       
  1273           // Put in garbage to delete later. Will need the properties
       
  1274           // for the remove_if of the out-edges.
       
  1275           garbage.push_back((*out_i.base()).get_iter());
       
  1276         }
       
  1277 
       
  1278       // Now remove the edges from this out-edge list.
       
  1279       typename Config::out_edge_iterator first, last;
       
  1280       tie(first, last) = out_edges(u, g);
       
  1281       typedef typename Config::edge_parallel_category Cat;
       
  1282       detail::remove_directed_edge_if_dispatch
       
  1283         (first, last, g.out_edge_list(u), pred, Cat());
       
  1284 
       
  1285       // Now delete the edge properties from the g.m_edges list
       
  1286       for (typename Garbage::iterator i = garbage.begin();
       
  1287            i != garbage.end(); ++i)
       
  1288         g.m_edges.erase(*i);
       
  1289     }
       
  1290     template <class Config, class Predicate>
       
  1291     inline void
       
  1292     remove_in_edge_if(typename Config::vertex_descriptor v, Predicate pred,
       
  1293                       bidirectional_graph_helper_with_property<Config>& g_)
       
  1294     {
       
  1295       typedef typename Config::global_edgelist_selector EdgeListS;
       
  1296       BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
       
  1297 
       
  1298       typedef typename Config::graph_type graph_type;
       
  1299       typedef typename Config::OutEdgeList::value_type::property_type PropT;
       
  1300       graph_type& g = static_cast<graph_type&>(g_);
       
  1301 
       
  1302       typedef typename Config::EdgeIter EdgeIter;
       
  1303       typedef std::vector<EdgeIter> Garbage;
       
  1304       Garbage garbage;
       
  1305 
       
  1306       // First remove the edges from the sources' out-edge lists and
       
  1307       // from the graph's edge set list.
       
  1308       typename Config::in_edge_iterator in_i, in_end;
       
  1309       for (tie(in_i, in_end) = in_edges(v, g); in_i != in_end; ++in_i)
       
  1310         if (pred(*in_i)) {
       
  1311           typename Config::vertex_descriptor u = source(*in_i, g);
       
  1312           detail::remove_directed_edge_dispatch
       
  1313             (*in_i, g.out_edge_list(u), *(PropT*)(*in_i).get_property());
       
  1314           // Put in garbage to delete later. Will need the properties
       
  1315           // for the remove_if of the out-edges.
       
  1316           garbage.push_back((*in_i.base()).get_iter());
       
  1317         }
       
  1318       // Now remove the edges from this in-edge list.
       
  1319       typename Config::in_edge_iterator first, last;
       
  1320       tie(first, last) = in_edges(v, g);
       
  1321       typedef typename Config::edge_parallel_category Cat;
       
  1322       detail::remove_directed_edge_if_dispatch
       
  1323         (first, last, in_edge_list(g, v), pred, Cat());
       
  1324 
       
  1325       // Now delete the edge properties from the g.m_edges list
       
  1326       for (typename Garbage::iterator i = garbage.begin();
       
  1327            i != garbage.end(); ++i)
       
  1328         g.m_edges.erase(*i);
       
  1329     }
       
  1330 
       
  1331     // O(1)
       
  1332     template <class Config>
       
  1333     inline typename Config::edges_size_type
       
  1334     num_edges(const bidirectional_graph_helper_with_property<Config>& g_) 
       
  1335     {
       
  1336       typedef typename Config::graph_type graph_type;
       
  1337       const graph_type& g = static_cast<const graph_type&>(g_);
       
  1338       return g.m_edges.size();
       
  1339     }
       
  1340     // O(E/V * E/V) for allow_parallel_edge_tag
       
  1341     // O(E/V * log(E/V)) for disallow_parallel_edge_tag
       
  1342     template <class Config>
       
  1343     inline void
       
  1344     clear_vertex(typename Config::vertex_descriptor u,
       
  1345                  bidirectional_graph_helper_with_property<Config>& g_)
       
  1346     {
       
  1347       typedef typename Config::global_edgelist_selector EdgeListS;
       
  1348       BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
       
  1349 
       
  1350       typedef typename Config::graph_type graph_type;
       
  1351       typedef typename Config::edge_parallel_category Cat;
       
  1352       graph_type& g = static_cast<graph_type&>(g_);
       
  1353       typename Config::OutEdgeList& el = g.out_edge_list(u);
       
  1354       typename Config::OutEdgeList::iterator 
       
  1355         ei = el.begin(), ei_end = el.end();
       
  1356       for (; ei != ei_end; ++ei) {
       
  1357         detail::erase_from_incidence_list
       
  1358           (in_edge_list(g, (*ei).get_target()), u, Cat());
       
  1359         g.m_edges.erase((*ei).get_iter());
       
  1360       }      
       
  1361       typename Config::InEdgeList& in_el = in_edge_list(g, u);
       
  1362       typename Config::InEdgeList::iterator 
       
  1363         in_ei = in_el.begin(), in_ei_end = in_el.end();
       
  1364       for (; in_ei != in_ei_end; ++in_ei) {
       
  1365         detail::erase_from_incidence_list
       
  1366           (g.out_edge_list((*in_ei).get_target()), u, Cat());
       
  1367         g.m_edges.erase((*in_ei).get_iter());   
       
  1368       }
       
  1369       g.out_edge_list(u).clear();
       
  1370       in_edge_list(g, u).clear();
       
  1371     }
       
  1372 
       
  1373     template <class Config>
       
  1374     inline void
       
  1375     clear_out_edges(typename Config::vertex_descriptor u,
       
  1376                     bidirectional_graph_helper_with_property<Config>& g_)
       
  1377     {
       
  1378       typedef typename Config::global_edgelist_selector EdgeListS;
       
  1379       BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
       
  1380 
       
  1381       typedef typename Config::graph_type graph_type;
       
  1382       typedef typename Config::edge_parallel_category Cat;
       
  1383       graph_type& g = static_cast<graph_type&>(g_);
       
  1384       typename Config::OutEdgeList& el = g.out_edge_list(u);
       
  1385       typename Config::OutEdgeList::iterator 
       
  1386         ei = el.begin(), ei_end = el.end();
       
  1387       for (; ei != ei_end; ++ei) {
       
  1388         detail::erase_from_incidence_list
       
  1389           (in_edge_list(g, (*ei).get_target()), u, Cat());
       
  1390         g.m_edges.erase((*ei).get_iter());
       
  1391       }      
       
  1392       g.out_edge_list(u).clear();
       
  1393     }
       
  1394 
       
  1395     template <class Config>
       
  1396     inline void
       
  1397     clear_in_edges(typename Config::vertex_descriptor u,
       
  1398                    bidirectional_graph_helper_with_property<Config>& g_)
       
  1399     {
       
  1400       typedef typename Config::global_edgelist_selector EdgeListS;
       
  1401       BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
       
  1402 
       
  1403       typedef typename Config::graph_type graph_type;
       
  1404       typedef typename Config::edge_parallel_category Cat;
       
  1405       graph_type& g = static_cast<graph_type&>(g_);
       
  1406       typename Config::InEdgeList& in_el = in_edge_list(g, u);
       
  1407       typename Config::InEdgeList::iterator 
       
  1408         in_ei = in_el.begin(), in_ei_end = in_el.end();
       
  1409       for (; in_ei != in_ei_end; ++in_ei) {
       
  1410         detail::erase_from_incidence_list
       
  1411           (g.out_edge_list((*in_ei).get_target()), u, Cat());
       
  1412         g.m_edges.erase((*in_ei).get_iter());   
       
  1413       }
       
  1414       in_edge_list(g, u).clear();
       
  1415     }
       
  1416 
       
  1417     // O(1) for allow_parallel_edge_tag
       
  1418     // O(log(E/V)) for disallow_parallel_edge_tag
       
  1419     template <class Config>
       
  1420     inline std::pair<typename Config::edge_descriptor, bool>
       
  1421     add_edge(typename Config::vertex_descriptor u,
       
  1422              typename Config::vertex_descriptor v, 
       
  1423              const typename Config::edge_property_type& p,
       
  1424              bidirectional_graph_helper_with_property<Config>& g_)
       
  1425     {
       
  1426       typedef typename Config::graph_type graph_type;
       
  1427       graph_type& g = static_cast<graph_type&>(g_);
       
  1428       typedef typename Config::edge_descriptor edge_descriptor;
       
  1429       typedef typename Config::StoredEdge StoredEdge;
       
  1430       bool inserted;
       
  1431       typename Config::EdgeContainer::value_type e(u, v, p);
       
  1432       typename Config::EdgeContainer::iterator p_iter 
       
  1433         = graph_detail::push(g.m_edges, e).first;
       
  1434       typename Config::OutEdgeList::iterator i;
       
  1435       boost::tie(i, inserted) = boost::graph_detail::push(g.out_edge_list(u), 
       
  1436                                         StoredEdge(v, p_iter, &g.m_edges));
       
  1437       if (inserted) {
       
  1438         boost::graph_detail::push(in_edge_list(g, v), StoredEdge(u, p_iter, &g.m_edges));
       
  1439         return std::make_pair(edge_descriptor(u, v, &p_iter->m_property), 
       
  1440                               true);
       
  1441       } else {
       
  1442         g.m_edges.erase(p_iter);
       
  1443         return std::make_pair(edge_descriptor(u, v, 
       
  1444                                      &i->get_iter()->get_property()), 
       
  1445                               false);
       
  1446       }
       
  1447     }
       
  1448 
       
  1449     template <class Config>
       
  1450     inline std::pair<typename Config::edge_descriptor, bool>
       
  1451     add_edge(typename Config::vertex_descriptor u,
       
  1452              typename Config::vertex_descriptor v,
       
  1453              bidirectional_graph_helper_with_property<Config>& g_)
       
  1454     {
       
  1455       typename Config::edge_property_type p;
       
  1456       return add_edge(u, v, p, g_);
       
  1457     }
       
  1458     // O(1)
       
  1459     template <class Config>
       
  1460     inline typename Config::degree_size_type
       
  1461     degree(typename Config::vertex_descriptor u, 
       
  1462            const bidirectional_graph_helper_with_property<Config>& g_)
       
  1463     {
       
  1464       typedef typename Config::graph_type graph_type;
       
  1465       const graph_type& g = static_cast<const graph_type&>(g_);
       
  1466       return in_degree(u, g) + out_degree(u, g);
       
  1467     }
       
  1468 
       
  1469     //=========================================================================
       
  1470     // Adjacency List Helper Class
       
  1471 
       
  1472     template <class Config, class Base>
       
  1473     struct adj_list_helper : public Base
       
  1474     {
       
  1475       typedef typename Config::graph_type AdjList;
       
  1476       typedef typename Config::vertex_descriptor vertex_descriptor;
       
  1477       typedef typename Config::edge_descriptor edge_descriptor;
       
  1478       typedef typename Config::out_edge_iterator out_edge_iterator;
       
  1479       typedef typename Config::in_edge_iterator in_edge_iterator;
       
  1480       typedef typename Config::adjacency_iterator adjacency_iterator;
       
  1481       typedef typename Config::inv_adjacency_iterator inv_adjacency_iterator;
       
  1482       typedef typename Config::vertex_iterator vertex_iterator;
       
  1483       typedef typename Config::edge_iterator edge_iterator;
       
  1484       typedef typename Config::directed_category directed_category;
       
  1485       typedef typename Config::edge_parallel_category edge_parallel_category;
       
  1486       typedef typename Config::vertices_size_type vertices_size_type;
       
  1487       typedef typename Config::edges_size_type edges_size_type;
       
  1488       typedef typename Config::degree_size_type degree_size_type;
       
  1489       typedef typename Config::StoredEdge StoredEdge;
       
  1490       typedef typename Config::edge_property_type edge_property_type;
       
  1491 
       
  1492       typedef typename Config::global_edgelist_selector
       
  1493         global_edgelist_selector;
       
  1494 
       
  1495       //    protected:
       
  1496 
       
  1497       // The edge_dispatch() functions should be static, but
       
  1498       // Borland gets confused about constness.
       
  1499 
       
  1500       // O(E/V)
       
  1501       inline std::pair<edge_descriptor,bool>      
       
  1502       edge_dispatch(const AdjList& g, 
       
  1503                     vertex_descriptor u, vertex_descriptor v, 
       
  1504                     boost::allow_parallel_edge_tag) const
       
  1505       {
       
  1506         bool found;
       
  1507         const typename Config::OutEdgeList& el = g.out_edge_list(u);
       
  1508         typename Config::OutEdgeList::const_iterator 
       
  1509           i = std::find_if(el.begin(), el.end(), 
       
  1510                            detail::target_is<vertex_descriptor>(v));
       
  1511         found = (i != g.out_edge_list(u).end());
       
  1512         if (found)
       
  1513           return std::make_pair(edge_descriptor(u, v, &(*i).get_property()),
       
  1514                                 true);
       
  1515         else
       
  1516           return std::make_pair(edge_descriptor(u, v, 0), false);
       
  1517       }
       
  1518       // O(log(E/V))
       
  1519       inline std::pair<edge_descriptor,bool>      
       
  1520       edge_dispatch(const AdjList& g, 
       
  1521                     vertex_descriptor u, vertex_descriptor v, 
       
  1522                     boost::disallow_parallel_edge_tag) const
       
  1523       {
       
  1524         bool found;
       
  1525         /* According to the standard, this should be iterator, not const_iterator,
       
  1526            but the VC++ std::set::find() const returns const_iterator.
       
  1527            And since iterator should be convertible to const_iterator, the
       
  1528            following should work everywhere. -Jeremy */
       
  1529         typename Config::OutEdgeList::const_iterator 
       
  1530           i = g.out_edge_list(u).find(StoredEdge(v)),
       
  1531           end = g.out_edge_list(u).end();
       
  1532         found = (i != end);
       
  1533         if (found)
       
  1534           return std::make_pair(edge_descriptor(u, v, &(*i).get_property()),
       
  1535                                 true);
       
  1536         else
       
  1537           return std::make_pair(edge_descriptor(u, v, 0), false);
       
  1538       }
       
  1539     };
       
  1540 
       
  1541     template <class Config, class Base>
       
  1542     inline std::pair<typename Config::adjacency_iterator, 
       
  1543                      typename Config::adjacency_iterator>
       
  1544     adjacent_vertices(typename Config::vertex_descriptor u, 
       
  1545                       const adj_list_helper<Config, Base>& g_)
       
  1546     {
       
  1547       typedef typename Config::graph_type AdjList;
       
  1548       const AdjList& cg = static_cast<const AdjList&>(g_);
       
  1549       AdjList& g = const_cast<AdjList&>(cg);
       
  1550       typedef typename Config::adjacency_iterator adjacency_iterator;
       
  1551       typename Config::out_edge_iterator first, last;
       
  1552       boost::tie(first, last) = out_edges(u, g);
       
  1553       return std::make_pair(adjacency_iterator(first, &g),
       
  1554                             adjacency_iterator(last, &g));
       
  1555     }
       
  1556     template <class Config, class Base>
       
  1557     inline std::pair<typename Config::inv_adjacency_iterator, 
       
  1558                      typename Config::inv_adjacency_iterator>
       
  1559     inv_adjacent_vertices(typename Config::vertex_descriptor u, 
       
  1560                           const adj_list_helper<Config, Base>& g_)
       
  1561     {
       
  1562       typedef typename Config::graph_type AdjList;
       
  1563       const AdjList& cg = static_cast<const AdjList&>(g_);
       
  1564       AdjList& g = const_cast<AdjList&>(cg);
       
  1565       typedef typename Config::inv_adjacency_iterator inv_adjacency_iterator;
       
  1566       typename Config::in_edge_iterator first, last;
       
  1567       boost::tie(first, last) = in_edges(u, g);
       
  1568       return std::make_pair(inv_adjacency_iterator(first, &g),
       
  1569                             inv_adjacency_iterator(last, &g));
       
  1570     }
       
  1571     template <class Config, class Base>
       
  1572     inline std::pair<typename Config::out_edge_iterator, 
       
  1573                      typename Config::out_edge_iterator>
       
  1574     out_edges(typename Config::vertex_descriptor u, 
       
  1575               const adj_list_helper<Config, Base>& g_)
       
  1576     {
       
  1577       typedef typename Config::graph_type AdjList;
       
  1578       typedef typename Config::out_edge_iterator out_edge_iterator;
       
  1579       const AdjList& cg = static_cast<const AdjList&>(g_);
       
  1580       AdjList& g = const_cast<AdjList&>(cg);
       
  1581       return
       
  1582         std::make_pair(out_edge_iterator(g.out_edge_list(u).begin(), u),
       
  1583                        out_edge_iterator(g.out_edge_list(u).end(), u));
       
  1584     }
       
  1585     template <class Config, class Base>
       
  1586     inline std::pair<typename Config::vertex_iterator, 
       
  1587                      typename Config::vertex_iterator>
       
  1588     vertices(const adj_list_helper<Config, Base>& g_)
       
  1589     {
       
  1590       typedef typename Config::graph_type AdjList;
       
  1591       const AdjList& cg = static_cast<const AdjList&>(g_);
       
  1592       AdjList& g = const_cast<AdjList&>(cg);
       
  1593       return std::make_pair( g.vertex_set().begin(), g.vertex_set().end() );
       
  1594     }
       
  1595     template <class Config, class Base>
       
  1596     inline typename Config::vertices_size_type
       
  1597     num_vertices(const adj_list_helper<Config, Base>& g_)
       
  1598     {
       
  1599       typedef typename Config::graph_type AdjList;
       
  1600       const AdjList& g = static_cast<const AdjList&>(g_);
       
  1601       return g.vertex_set().size();
       
  1602     }
       
  1603     template <class Config, class Base>
       
  1604     inline typename Config::degree_size_type
       
  1605     out_degree(typename Config::vertex_descriptor u, 
       
  1606                const adj_list_helper<Config, Base>& g_)
       
  1607     {
       
  1608       typedef typename Config::graph_type AdjList;
       
  1609       const AdjList& g = static_cast<const AdjList&>(g_);
       
  1610       return g.out_edge_list(u).size();
       
  1611     }
       
  1612     template <class Config, class Base>
       
  1613     inline std::pair<typename Config::edge_descriptor, bool>
       
  1614     edge(typename Config::vertex_descriptor u, 
       
  1615          typename Config::vertex_descriptor v, 
       
  1616          const adj_list_helper<Config, Base>& g_)
       
  1617     {
       
  1618       typedef typename Config::graph_type Graph;
       
  1619       typedef typename Config::edge_parallel_category Cat;
       
  1620       const Graph& g = static_cast<const Graph&>(g_);
       
  1621       return g_.edge_dispatch(g, u, v, Cat());
       
  1622     }
       
  1623     template <class Config, class Base>
       
  1624     inline std::pair<typename Config::out_edge_iterator,
       
  1625                      typename Config::out_edge_iterator>
       
  1626     edge_range(typename Config::vertex_descriptor u,
       
  1627                typename Config::vertex_descriptor v,
       
  1628                const adj_list_helper<Config, Base>& g_)
       
  1629     {
       
  1630       typedef typename Config::graph_type Graph;
       
  1631       typedef typename Config::StoredEdge StoredEdge;
       
  1632       const Graph& cg = static_cast<const Graph&>(g_);
       
  1633       Graph& g = const_cast<Graph&>(cg);
       
  1634       typedef typename Config::out_edge_iterator out_edge_iterator;
       
  1635       typename Config::OutEdgeList& el = g.out_edge_list(u);
       
  1636       typename Config::OutEdgeList::iterator first, last;
       
  1637       typename Config::EdgeContainer fake_edge_container;
       
  1638       tie(first, last) = 
       
  1639         std::equal_range(el.begin(), el.end(), 
       
  1640                          StoredEdge(v, fake_edge_container.end(),
       
  1641                                     &fake_edge_container));
       
  1642       return std::make_pair(out_edge_iterator(first, u),
       
  1643                             out_edge_iterator(last, u));
       
  1644     }
       
  1645 
       
  1646     template <class Config>
       
  1647     inline typename Config::degree_size_type
       
  1648     in_degree(typename Config::vertex_descriptor u, 
       
  1649               const directed_edges_helper<Config>& g_)
       
  1650     {
       
  1651       typedef typename Config::graph_type Graph;
       
  1652       const Graph& cg = static_cast<const Graph&>(g_);
       
  1653       Graph& g = const_cast<Graph&>(cg);
       
  1654       return in_edge_list(g, u).size();
       
  1655     }
       
  1656 
       
  1657     namespace detail {
       
  1658       template <class Config, class Base, class Property>
       
  1659       inline
       
  1660       typename boost::property_map<typename Config::graph_type,
       
  1661         Property>::type
       
  1662       get_dispatch(adj_list_helper<Config,Base>&, Property, 
       
  1663                    boost::edge_property_tag) {
       
  1664         typedef typename Config::graph_type Graph;
       
  1665         typedef typename boost::property_map<Graph, Property>::type PA;
       
  1666         return PA();
       
  1667       }
       
  1668       template <class Config, class Base, class Property>
       
  1669       inline
       
  1670       typename boost::property_map<typename Config::graph_type, 
       
  1671         Property>::const_type
       
  1672       get_dispatch(const adj_list_helper<Config,Base>&, Property, 
       
  1673                    boost::edge_property_tag) {
       
  1674         typedef typename Config::graph_type Graph;
       
  1675         typedef typename boost::property_map<Graph, Property>::const_type PA;
       
  1676         return PA();
       
  1677       }
       
  1678 
       
  1679       template <class Config, class Base, class Property>
       
  1680       inline
       
  1681       typename boost::property_map<typename Config::graph_type, 
       
  1682         Property>::type
       
  1683       get_dispatch(adj_list_helper<Config,Base>& g, Property, 
       
  1684                    boost::vertex_property_tag) {
       
  1685         typedef typename Config::graph_type Graph;
       
  1686         typedef typename boost::property_map<Graph, Property>::type PA;
       
  1687         return PA(&static_cast<Graph&>(g));
       
  1688       }
       
  1689       template <class Config, class Base, class Property>
       
  1690       inline
       
  1691       typename boost::property_map<typename Config::graph_type,
       
  1692         Property>::const_type
       
  1693       get_dispatch(const adj_list_helper<Config, Base>& g, Property, 
       
  1694                    boost::vertex_property_tag) {
       
  1695         typedef typename Config::graph_type Graph;
       
  1696         typedef typename boost::property_map<Graph, Property>::const_type PA;
       
  1697         const Graph& cg = static_cast<const Graph&>(g);
       
  1698         return PA(&cg);
       
  1699       }
       
  1700 
       
  1701     } // namespace detail
       
  1702 
       
  1703     // Implementation of the PropertyGraph interface
       
  1704     template <class Config, class Base, class Property>
       
  1705     inline
       
  1706     typename boost::property_map<typename Config::graph_type, Property>::type
       
  1707     get(Property p, adj_list_helper<Config, Base>& g) {
       
  1708       typedef typename property_kind<Property>::type Kind;
       
  1709       return detail::get_dispatch(g, p, Kind());
       
  1710     }
       
  1711     template <class Config, class Base, class Property>
       
  1712     inline
       
  1713     typename boost::property_map<typename Config::graph_type, 
       
  1714       Property>::const_type
       
  1715     get(Property p, const adj_list_helper<Config, Base>& g) {
       
  1716       typedef typename property_kind<Property>::type Kind;
       
  1717       return detail::get_dispatch(g, p, Kind());
       
  1718     }
       
  1719 
       
  1720     template <class Config, class Base, class Property, class Key>
       
  1721     inline
       
  1722     typename boost::property_traits<
       
  1723       typename boost::property_map<typename Config::graph_type, 
       
  1724         Property>::type
       
  1725     >::reference
       
  1726     get(Property p, adj_list_helper<Config, Base>& g, const Key& key) {
       
  1727       return get(get(p, g), key);
       
  1728     }
       
  1729 
       
  1730     template <class Config, class Base, class Property, class Key>
       
  1731     inline
       
  1732     typename boost::property_traits<
       
  1733       typename boost::property_map<typename Config::graph_type, 
       
  1734         Property>::const_type
       
  1735     >::reference
       
  1736     get(Property p, const adj_list_helper<Config, Base>& g, const Key& key) {
       
  1737       return get(get(p, g), key);
       
  1738     }
       
  1739 
       
  1740     template <class Config, class Base, class Property, class Key,class Value>
       
  1741     inline void
       
  1742     put(Property p, adj_list_helper<Config, Base>& g, 
       
  1743         const Key& key, const Value& value)
       
  1744     {
       
  1745       typedef typename Config::graph_type Graph;
       
  1746       typedef typename boost::property_map<Graph, Property>::type Map;
       
  1747       Map pmap = get(p, static_cast<Graph&>(g));
       
  1748       put(pmap, key, value);
       
  1749     }
       
  1750 
       
  1751 
       
  1752     //=========================================================================
       
  1753     // Generalize Adjacency List Implementation
       
  1754 
       
  1755     struct adj_list_tag { };
       
  1756 
       
  1757     template <class Derived, class Config, class Base>
       
  1758     class adj_list_impl
       
  1759       : public adj_list_helper<Config, Base>
       
  1760     {
       
  1761       typedef typename Config::OutEdgeList OutEdgeList;
       
  1762       typedef typename Config::InEdgeList InEdgeList;
       
  1763       typedef typename Config::StoredVertexList StoredVertexList;
       
  1764     public:
       
  1765       typedef typename Config::stored_vertex stored_vertex;
       
  1766       typedef typename Config::EdgeContainer EdgeContainer;
       
  1767       typedef typename Config::vertex_descriptor vertex_descriptor;
       
  1768       typedef typename Config::edge_descriptor edge_descriptor;
       
  1769       typedef typename Config::vertex_iterator vertex_iterator;
       
  1770       typedef typename Config::edge_iterator edge_iterator;
       
  1771       typedef typename Config::edge_parallel_category edge_parallel_category;
       
  1772       typedef typename Config::vertices_size_type vertices_size_type;
       
  1773       typedef typename Config::edges_size_type edges_size_type;
       
  1774       typedef typename Config::degree_size_type degree_size_type;
       
  1775       typedef typename Config::edge_property_type edge_property_type;
       
  1776       typedef adj_list_tag graph_tag;
       
  1777 
       
  1778       static vertex_descriptor null_vertex()
       
  1779       {
       
  1780         return 0;
       
  1781       }
       
  1782       
       
  1783       inline adj_list_impl() { }
       
  1784 
       
  1785       inline adj_list_impl(const adj_list_impl& x) {
       
  1786         copy_impl(x);
       
  1787       }
       
  1788       inline adj_list_impl& operator=(const adj_list_impl& x) {
       
  1789         this->clear();
       
  1790         copy_impl(x);
       
  1791         return *this;
       
  1792       }
       
  1793       inline void clear() {
       
  1794         for (typename StoredVertexList::iterator i = m_vertices.begin();
       
  1795              i != m_vertices.end(); ++i)
       
  1796           delete (stored_vertex*)*i;
       
  1797         m_vertices.clear();
       
  1798         m_edges.clear();
       
  1799       }
       
  1800       inline adj_list_impl(vertices_size_type num_vertices) {
       
  1801         for (vertices_size_type i = 0; i < num_vertices; ++i)
       
  1802           add_vertex(static_cast<Derived&>(*this));
       
  1803       }
       
  1804       template <class EdgeIterator>
       
  1805       inline adj_list_impl(vertices_size_type num_vertices,
       
  1806                            EdgeIterator first, EdgeIterator last)
       
  1807       {
       
  1808         vertex_descriptor* v = new vertex_descriptor[num_vertices];
       
  1809         for (vertices_size_type i = 0; i < num_vertices; ++i)
       
  1810           v[i] = add_vertex(static_cast<Derived&>(*this));
       
  1811 
       
  1812         while (first != last) {
       
  1813           add_edge(v[(*first).first], v[(*first).second], *this);
       
  1814           ++first;
       
  1815         }
       
  1816         delete [] v;
       
  1817       }
       
  1818       template <class EdgeIterator, class EdgePropertyIterator>
       
  1819       inline adj_list_impl(vertices_size_type num_vertices,
       
  1820                            EdgeIterator first, EdgeIterator last,
       
  1821                            EdgePropertyIterator ep_iter)
       
  1822       {
       
  1823         vertex_descriptor* v = new vertex_descriptor[num_vertices];
       
  1824         for (vertices_size_type i = 0; i < num_vertices; ++i)
       
  1825           v[i] = add_vertex(static_cast<Derived&>(*this));
       
  1826 
       
  1827         while (first != last) {
       
  1828           add_edge(v[(*first).first], v[(*first).second], *ep_iter, *this);
       
  1829           ++first;
       
  1830           ++ep_iter;
       
  1831         }
       
  1832         delete [] v;
       
  1833       }
       
  1834       ~adj_list_impl() {
       
  1835         for (typename StoredVertexList::iterator i = m_vertices.begin();
       
  1836              i != m_vertices.end(); ++i)
       
  1837           delete (stored_vertex*)*i;
       
  1838       }
       
  1839       //    protected:
       
  1840       inline OutEdgeList& out_edge_list(vertex_descriptor v) {
       
  1841         stored_vertex* sv = (stored_vertex*)v;
       
  1842         return sv->m_out_edges;
       
  1843       }
       
  1844       inline const OutEdgeList& out_edge_list(vertex_descriptor v) const {
       
  1845         stored_vertex* sv = (stored_vertex*)v;
       
  1846         return sv->m_out_edges;
       
  1847       }
       
  1848       inline StoredVertexList& vertex_set() { return m_vertices; }
       
  1849       inline const StoredVertexList& vertex_set() const { return m_vertices; }
       
  1850 
       
  1851       inline void copy_impl(const adj_list_impl& x_) 
       
  1852       {
       
  1853         const Derived& x = static_cast<const Derived&>(x_);
       
  1854 
       
  1855         // Would be better to have a constant time way to get from
       
  1856         // vertices in x to the corresponding vertices in *this.
       
  1857         std::map<stored_vertex*,stored_vertex*> vertex_map;
       
  1858 
       
  1859         // Copy the stored vertex objects by adding each vertex
       
  1860         // and copying its property object.
       
  1861         vertex_iterator vi, vi_end;
       
  1862         for (tie(vi, vi_end) = vertices(x); vi != vi_end; ++vi) {
       
  1863           stored_vertex* v = (stored_vertex*)add_vertex(*this);
       
  1864           v->m_property = ((stored_vertex*)*vi)->m_property;
       
  1865           vertex_map[(stored_vertex*)*vi] = v;
       
  1866         }
       
  1867         // Copy the edges by adding each edge and copying its
       
  1868         // property object.
       
  1869         edge_iterator ei, ei_end;
       
  1870         for (tie(ei, ei_end) = edges(x); ei != ei_end; ++ei) {
       
  1871           edge_descriptor e;
       
  1872           bool inserted; 
       
  1873           vertex_descriptor s = source(*ei,x), t = target(*ei,x);
       
  1874           tie(e, inserted) = add_edge(vertex_map[(stored_vertex*)s], 
       
  1875                                       vertex_map[(stored_vertex*)t], *this);
       
  1876           *((edge_property_type*)e.m_eproperty)
       
  1877             = *((edge_property_type*)(*ei).m_eproperty);
       
  1878         }
       
  1879       }
       
  1880 
       
  1881 
       
  1882       typename Config::EdgeContainer m_edges;
       
  1883       StoredVertexList m_vertices;
       
  1884     };
       
  1885 
       
  1886     // O(1)
       
  1887     template <class Derived, class Config, class Base>
       
  1888     inline typename Config::vertex_descriptor
       
  1889     add_vertex(adj_list_impl<Derived, Config, Base>& g_)
       
  1890     {
       
  1891       Derived& g = static_cast<Derived&>(g_);
       
  1892       typedef typename Config::stored_vertex stored_vertex;
       
  1893       stored_vertex* v = new stored_vertex;
       
  1894       typename Config::StoredVertexList::iterator pos;
       
  1895       bool inserted;
       
  1896       boost::tie(pos,inserted) = boost::graph_detail::push(g.m_vertices, v);
       
  1897       v->m_position = pos;
       
  1898       return v;
       
  1899     }
       
  1900     // O(1)
       
  1901     template <class Derived, class Config, class Base>
       
  1902     inline typename Config::vertex_descriptor
       
  1903     add_vertex(const typename Config::vertex_property_type& p,
       
  1904                adj_list_impl<Derived, Config, Base>& g_)
       
  1905     {
       
  1906       Derived& g = static_cast<Derived&>(g_);
       
  1907       typedef typename Config::stored_vertex stored_vertex;
       
  1908       stored_vertex* v = new stored_vertex(p);
       
  1909       typename Config::StoredVertexList::iterator pos;
       
  1910       bool inserted;
       
  1911       boost::tie(pos,inserted) = boost::graph_detail::push(g.m_vertices, v);
       
  1912       v->m_position = pos;
       
  1913       return v;
       
  1914     }
       
  1915     // O(1)
       
  1916     template <class Derived, class Config, class Base>
       
  1917     inline void remove_vertex(typename Config::vertex_descriptor u,
       
  1918                               adj_list_impl<Derived, Config, Base>& g_)
       
  1919     {
       
  1920       typedef typename Config::stored_vertex stored_vertex;
       
  1921       Derived& g = static_cast<Derived&>(g_);
       
  1922       stored_vertex* su = (stored_vertex*)u;
       
  1923       g.m_vertices.erase(su->m_position);
       
  1924       delete su;
       
  1925     }
       
  1926     // O(V)
       
  1927     template <class Derived, class Config, class Base>
       
  1928     inline typename Config::vertex_descriptor
       
  1929     vertex(typename Config::vertices_size_type n, 
       
  1930            const adj_list_impl<Derived, Config, Base>& g_)
       
  1931     {
       
  1932       const Derived& g = static_cast<const Derived&>(g_);
       
  1933       typename Config::vertex_iterator i = vertices(g).first;
       
  1934       while (n--) ++i; // std::advance(i, n); (not VC++ portable)
       
  1935       return *i;
       
  1936     }
       
  1937 
       
  1938     //=========================================================================
       
  1939     // Vector-Backbone Adjacency List Implementation
       
  1940 
       
  1941     namespace detail {
       
  1942 
       
  1943       template <class Graph, class vertex_descriptor>
       
  1944       inline void 
       
  1945       remove_vertex_dispatch(Graph& g, vertex_descriptor u, 
       
  1946                              boost::directed_tag)
       
  1947       {
       
  1948         typedef typename Graph::edge_parallel_category edge_parallel_category;
       
  1949         g.m_vertices.erase(g.m_vertices.begin() + u);
       
  1950         vertex_descriptor V = num_vertices(g);
       
  1951         if (u != V) {
       
  1952           for (vertex_descriptor v = 0; v < V; ++v)
       
  1953             reindex_edge_list(g.out_edge_list(v), u, edge_parallel_category());
       
  1954         }
       
  1955       }
       
  1956 
       
  1957       template <class Graph, class vertex_descriptor>
       
  1958       inline void 
       
  1959       remove_vertex_dispatch(Graph& g, vertex_descriptor u, 
       
  1960                              boost::undirected_tag)
       
  1961       {
       
  1962         typedef typename Graph::global_edgelist_selector EdgeListS;
       
  1963         BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
       
  1964 
       
  1965         typedef typename Graph::edge_parallel_category edge_parallel_category;
       
  1966         g.m_vertices.erase(g.m_vertices.begin() + u);
       
  1967         vertex_descriptor V = num_vertices(g);
       
  1968         for (vertex_descriptor v = 0; v < V; ++v)
       
  1969           reindex_edge_list(g.out_edge_list(v), u, 
       
  1970                             edge_parallel_category());
       
  1971         typedef typename Graph::EdgeContainer Container;
       
  1972         typedef typename Container::iterator Iter;
       
  1973         Iter ei = g.m_edges.begin(), ei_end = g.m_edges.end();
       
  1974         for (; ei != ei_end; ++ei) {
       
  1975           if (ei->m_source > u)
       
  1976             --ei->m_source;
       
  1977           if (ei->m_target > u)
       
  1978             --ei->m_target;
       
  1979         }
       
  1980       }
       
  1981       template <class Graph, class vertex_descriptor>
       
  1982       inline void 
       
  1983       remove_vertex_dispatch(Graph& g, vertex_descriptor u, 
       
  1984                              boost::bidirectional_tag)
       
  1985       {
       
  1986         typedef typename Graph::global_edgelist_selector EdgeListS;
       
  1987         BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
       
  1988 
       
  1989         typedef typename Graph::edge_parallel_category edge_parallel_category;
       
  1990         g.m_vertices.erase(g.m_vertices.begin() + u);
       
  1991         vertex_descriptor V = num_vertices(g);
       
  1992         vertex_descriptor v;
       
  1993         if (u != V) {
       
  1994           for (v = 0; v < V; ++v)
       
  1995             reindex_edge_list(g.out_edge_list(v), u, 
       
  1996                               edge_parallel_category());
       
  1997           for (v = 0; v < V; ++v)
       
  1998             reindex_edge_list(in_edge_list(g, v), u, 
       
  1999                               edge_parallel_category());
       
  2000 
       
  2001           typedef typename Graph::EdgeContainer Container;
       
  2002           typedef typename Container::iterator Iter;
       
  2003           Iter ei = g.m_edges.begin(), ei_end = g.m_edges.end();
       
  2004           for (; ei != ei_end; ++ei) {
       
  2005             if (ei->m_source > u)
       
  2006               --ei->m_source;
       
  2007             if (ei->m_target > u)
       
  2008               --ei->m_target;
       
  2009           }
       
  2010         }
       
  2011       }
       
  2012 
       
  2013       template <class EdgeList, class vertex_descriptor>
       
  2014       inline void
       
  2015       reindex_edge_list(EdgeList& el, vertex_descriptor u, 
       
  2016                         boost::allow_parallel_edge_tag)
       
  2017       {
       
  2018         typename EdgeList::iterator ei = el.begin(), e_end = el.end();
       
  2019         for (; ei != e_end; ++ei)
       
  2020           if ((*ei).get_target() > u)
       
  2021             --(*ei).get_target();
       
  2022       }
       
  2023       template <class EdgeList, class vertex_descriptor>
       
  2024       inline void
       
  2025       reindex_edge_list(EdgeList& el, vertex_descriptor u, 
       
  2026                         boost::disallow_parallel_edge_tag)
       
  2027       {
       
  2028         typename EdgeList::iterator ei = el.begin(), e_end = el.end();
       
  2029         while (ei != e_end) {
       
  2030           typename EdgeList::value_type ce = *ei;
       
  2031           ++ei;
       
  2032           if (ce.get_target() > u) {
       
  2033             el.erase(ce);
       
  2034             --ce.get_target();
       
  2035             el.insert(ce);
       
  2036           }
       
  2037         }
       
  2038       }
       
  2039     } // namespace detail
       
  2040 
       
  2041     struct vec_adj_list_tag { };
       
  2042     
       
  2043     template <class Graph, class Config, class Base>
       
  2044     class vec_adj_list_impl
       
  2045       : public adj_list_helper<Config, Base>
       
  2046     {
       
  2047       typedef typename Config::OutEdgeList OutEdgeList;
       
  2048       typedef typename Config::InEdgeList InEdgeList;
       
  2049       typedef typename Config::StoredVertexList StoredVertexList; 
       
  2050     public:
       
  2051       typedef typename Config::vertex_descriptor vertex_descriptor;
       
  2052       typedef typename Config::edge_descriptor edge_descriptor;
       
  2053       typedef typename Config::out_edge_iterator out_edge_iterator;
       
  2054       typedef typename Config::edge_iterator edge_iterator;
       
  2055       typedef typename Config::directed_category directed_category;
       
  2056       typedef typename Config::vertices_size_type vertices_size_type;
       
  2057       typedef typename Config::edges_size_type edges_size_type;
       
  2058       typedef typename Config::degree_size_type degree_size_type;
       
  2059       typedef typename Config::StoredEdge StoredEdge;
       
  2060       typedef typename Config::stored_vertex stored_vertex;
       
  2061       typedef typename Config::EdgeContainer EdgeContainer;
       
  2062       typedef typename Config::edge_property_type edge_property_type;
       
  2063       typedef vec_adj_list_tag graph_tag;
       
  2064 
       
  2065       static vertex_descriptor null_vertex()
       
  2066       {
       
  2067         return (std::numeric_limits<vertex_descriptor>::max)();
       
  2068       }
       
  2069       
       
  2070       inline vec_adj_list_impl() { }
       
  2071 
       
  2072       inline vec_adj_list_impl(const vec_adj_list_impl& x) {
       
  2073         copy_impl(x);
       
  2074       }
       
  2075       inline vec_adj_list_impl& operator=(const vec_adj_list_impl& x) {
       
  2076         this->clear();
       
  2077         copy_impl(x);
       
  2078         return *this;
       
  2079       }
       
  2080       inline void clear() {
       
  2081         m_vertices.clear();
       
  2082         m_edges.clear();
       
  2083       }
       
  2084 
       
  2085       inline vec_adj_list_impl(vertices_size_type _num_vertices)
       
  2086         : m_vertices(_num_vertices) { }
       
  2087 
       
  2088       template <class EdgeIterator>
       
  2089       inline vec_adj_list_impl(vertices_size_type num_vertices,
       
  2090                                EdgeIterator first, EdgeIterator last)
       
  2091         : m_vertices(num_vertices)
       
  2092       {
       
  2093         while (first != last) {
       
  2094           add_edge((*first).first, (*first).second, 
       
  2095                    static_cast<Graph&>(*this));
       
  2096           ++first;
       
  2097         }
       
  2098       }
       
  2099       template <class EdgeIterator, class EdgePropertyIterator>
       
  2100       inline vec_adj_list_impl(vertices_size_type num_vertices,
       
  2101                                EdgeIterator first, EdgeIterator last,
       
  2102                                EdgePropertyIterator ep_iter)
       
  2103         : m_vertices(num_vertices)
       
  2104       {
       
  2105         while (first != last) {
       
  2106           add_edge((*first).first, (*first).second, *ep_iter, 
       
  2107                    static_cast<Graph&>(*this));
       
  2108           ++first;
       
  2109           ++ep_iter;
       
  2110         }
       
  2111       }
       
  2112 
       
  2113       //    protected:
       
  2114       inline boost::integer_range<vertex_descriptor> vertex_set() const {
       
  2115         return boost::integer_range<vertex_descriptor>(0, m_vertices.size());
       
  2116       }
       
  2117       inline OutEdgeList& out_edge_list(vertex_descriptor v) {
       
  2118         return m_vertices[v].m_out_edges;
       
  2119       }
       
  2120       inline const OutEdgeList& out_edge_list(vertex_descriptor v) const {
       
  2121         return m_vertices[v].m_out_edges;
       
  2122       }
       
  2123       inline void copy_impl(const vec_adj_list_impl& x_) 
       
  2124       {
       
  2125         const Graph& x = static_cast<const Graph&>(x_);
       
  2126         // Copy the stored vertex objects by adding each vertex
       
  2127         // and copying its property object.
       
  2128         for (vertices_size_type i = 0; i < num_vertices(x); ++i) {
       
  2129           vertex_descriptor v = add_vertex(*this);
       
  2130           m_vertices[v].m_property = x.m_vertices[i].m_property;
       
  2131         }
       
  2132         // Copy the edges by adding each edge and copying its
       
  2133         // property object.
       
  2134         edge_iterator ei, ei_end;
       
  2135         for (tie(ei, ei_end) = edges(x); ei != ei_end; ++ei) {
       
  2136           edge_descriptor e;
       
  2137           bool inserted; 
       
  2138           tie(e, inserted) = add_edge(source(*ei,x), target(*ei,x) , *this);
       
  2139           *((edge_property_type*)e.m_eproperty)
       
  2140             = *((edge_property_type*)(*ei).m_eproperty);
       
  2141         }
       
  2142       }
       
  2143       typename Config::EdgeContainer m_edges;
       
  2144       StoredVertexList m_vertices;
       
  2145     };
       
  2146     // Had to make these non-members to avoid accidental instantiation
       
  2147     // on SGI MIPSpro C++
       
  2148     template <class G, class C, class B>
       
  2149     inline typename C::InEdgeList& 
       
  2150     in_edge_list(vec_adj_list_impl<G,C,B>& g, 
       
  2151                  typename C::vertex_descriptor v) {
       
  2152       return g.m_vertices[v].m_in_edges;
       
  2153     }
       
  2154     template <class G, class C, class B>
       
  2155     inline const typename C::InEdgeList& 
       
  2156     in_edge_list(const vec_adj_list_impl<G,C,B>& g, 
       
  2157                  typename C::vertex_descriptor v) {
       
  2158       return g.m_vertices[v].m_in_edges;
       
  2159     }
       
  2160 
       
  2161       // O(1)
       
  2162     template <class Graph, class Config, class Base>
       
  2163     inline typename Config::vertex_descriptor
       
  2164     add_vertex(vec_adj_list_impl<Graph, Config, Base>& g_) {
       
  2165       Graph& g = static_cast<Graph&>(g_);
       
  2166       g.m_vertices.resize(g.m_vertices.size() + 1);
       
  2167       return g.m_vertices.size() - 1;
       
  2168     }
       
  2169 
       
  2170     template <class Graph, class Config, class Base>
       
  2171     inline typename Config::vertex_descriptor
       
  2172     add_vertex(const typename Config::vertex_property_type& p,
       
  2173                vec_adj_list_impl<Graph, Config, Base>& g_) {
       
  2174       Graph& g = static_cast<Graph&>(g_);
       
  2175       typedef typename Config::stored_vertex stored_vertex;
       
  2176       g.m_vertices.push_back(stored_vertex(p));
       
  2177       return g.m_vertices.size() - 1;
       
  2178     }
       
  2179 
       
  2180     // Here we override the directed_graph_helper add_edge() function
       
  2181     // so that the number of vertices is automatically changed if
       
  2182     // either u or v is greater than the number of vertices.
       
  2183     template <class Graph, class Config, class Base>
       
  2184     inline std::pair<typename Config::edge_descriptor, bool>
       
  2185     add_edge(typename Config::vertex_descriptor u, 
       
  2186              typename Config::vertex_descriptor v,
       
  2187              const typename Config::edge_property_type& p,
       
  2188              vec_adj_list_impl<Graph, Config, Base>& g_)
       
  2189     {
       
  2190       BOOST_USING_STD_MAX();
       
  2191       typename Config::vertex_descriptor x = max BOOST_PREVENT_MACRO_SUBSTITUTION(u, v);
       
  2192       if (x >= num_vertices(g_))
       
  2193         g_.m_vertices.resize(x + 1);
       
  2194       adj_list_helper<Config, Base>& g = g_;
       
  2195       return add_edge(u, v, p, g);
       
  2196     }
       
  2197     template <class Graph, class Config, class Base>
       
  2198     inline std::pair<typename Config::edge_descriptor, bool>
       
  2199     add_edge(typename Config::vertex_descriptor u, 
       
  2200              typename Config::vertex_descriptor v,
       
  2201              vec_adj_list_impl<Graph, Config, Base>& g_)
       
  2202     {
       
  2203       typename Config::edge_property_type p;
       
  2204       return add_edge(u, v, p, g_);
       
  2205     }
       
  2206 
       
  2207 
       
  2208     // O(V + E)
       
  2209     template <class Graph, class Config, class Base>
       
  2210     inline void remove_vertex(typename Config::vertex_descriptor v,
       
  2211                               vec_adj_list_impl<Graph, Config, Base>& g_)
       
  2212     {
       
  2213       typedef typename Config::directed_category Cat;
       
  2214       Graph& g = static_cast<Graph&>(g_);
       
  2215       detail::remove_vertex_dispatch(g, v, Cat());
       
  2216     }
       
  2217     // O(1)
       
  2218     template <class Graph, class Config, class Base>
       
  2219     inline typename Config::vertex_descriptor 
       
  2220     vertex(typename Config::vertices_size_type n, 
       
  2221            const vec_adj_list_impl<Graph, Config, Base>&)
       
  2222     {
       
  2223       return n;
       
  2224     }
       
  2225 
       
  2226 
       
  2227   namespace detail {
       
  2228 
       
  2229     //=========================================================================
       
  2230     // Adjacency List Generator
       
  2231 
       
  2232     template <class Graph, class VertexListS, class OutEdgeListS,
       
  2233               class DirectedS, class VertexProperty, class EdgeProperty, 
       
  2234               class GraphProperty, class EdgeListS>
       
  2235     struct adj_list_gen
       
  2236     {
       
  2237       typedef typename detail::is_random_access<VertexListS>::type 
       
  2238         is_rand_access;
       
  2239       typedef typename has_property<EdgeProperty>::type has_edge_property; 
       
  2240       typedef typename DirectedS::is_directed_t DirectedT;
       
  2241       typedef typename DirectedS::is_bidir_t BidirectionalT;
       
  2242 
       
  2243       struct config
       
  2244       {
       
  2245         typedef OutEdgeListS edgelist_selector;
       
  2246         typedef EdgeListS global_edgelist_selector;
       
  2247 
       
  2248         typedef Graph graph_type;
       
  2249         typedef EdgeProperty edge_property_type;
       
  2250         typedef VertexProperty vertex_property_type;
       
  2251         typedef GraphProperty graph_property_type;
       
  2252         typedef std::size_t vertices_size_type;
       
  2253 
       
  2254         typedef adjacency_list_traits<OutEdgeListS, VertexListS, DirectedS> 
       
  2255            Traits;
       
  2256 
       
  2257         typedef typename Traits::directed_category directed_category;
       
  2258         typedef typename Traits::edge_parallel_category edge_parallel_category;
       
  2259         typedef typename Traits::vertex_descriptor vertex_descriptor;
       
  2260         typedef typename Traits::edge_descriptor edge_descriptor;
       
  2261 
       
  2262         typedef void* vertex_ptr; 
       
  2263 
       
  2264         // need to reorganize this to avoid instantiating stuff
       
  2265         // that doesn't get used -JGS
       
  2266 
       
  2267         // VertexList and vertex_iterator
       
  2268         typedef typename container_gen<VertexListS, 
       
  2269           vertex_ptr>::type SeqVertexList;
       
  2270         typedef boost::integer_range<std::size_t> RandVertexList;
       
  2271         typedef typename boost::ct_if_t<is_rand_access,
       
  2272           RandVertexList, SeqVertexList>::type VertexList;
       
  2273 
       
  2274         typedef typename VertexList::iterator vertex_iterator;
       
  2275 
       
  2276         // EdgeContainer and StoredEdge
       
  2277 
       
  2278         typedef typename container_gen<EdgeListS, 
       
  2279           list_edge<vertex_descriptor, EdgeProperty> >::type EdgeContainer;
       
  2280 
       
  2281         typedef typename ct_and<DirectedT, 
       
  2282              typename ct_not<BidirectionalT>::type >::type on_edge_storage;
       
  2283 
       
  2284         typedef typename boost::ct_if_t<on_edge_storage,
       
  2285           std::size_t, typename EdgeContainer::size_type
       
  2286         >::type edges_size_type;
       
  2287 
       
  2288         typedef typename EdgeContainer::iterator EdgeIter;
       
  2289 
       
  2290         typedef typename detail::is_random_access<EdgeListS>::type is_edge_ra;
       
  2291 
       
  2292         typedef typename boost::ct_if_t<on_edge_storage,
       
  2293           stored_edge_property<vertex_descriptor, EdgeProperty>,
       
  2294           typename boost::ct_if_t<is_edge_ra,
       
  2295             stored_ra_edge_iter<vertex_descriptor, EdgeContainer, EdgeProperty>,
       
  2296             stored_edge_iter<vertex_descriptor, EdgeIter, EdgeProperty>
       
  2297           >::type
       
  2298         >::type StoredEdge;
       
  2299 
       
  2300         // Adjacency Types
       
  2301 
       
  2302         typedef typename container_gen<OutEdgeListS, StoredEdge>::type 
       
  2303           OutEdgeList;
       
  2304         typedef typename OutEdgeList::size_type degree_size_type;
       
  2305         typedef typename OutEdgeList::iterator OutEdgeIter;
       
  2306 
       
  2307         typedef boost::detail::iterator_traits<OutEdgeIter> OutEdgeIterTraits;
       
  2308         typedef typename OutEdgeIterTraits::iterator_category OutEdgeIterCat;
       
  2309         typedef typename OutEdgeIterTraits::difference_type OutEdgeIterDiff;
       
  2310 
       
  2311         typedef out_edge_iter<
       
  2312             OutEdgeIter, vertex_descriptor, edge_descriptor, OutEdgeIterDiff
       
  2313         > out_edge_iterator;
       
  2314 
       
  2315         typedef typename adjacency_iterator_generator<graph_type,
       
  2316            vertex_descriptor, out_edge_iterator>::type adjacency_iterator;
       
  2317 
       
  2318         typedef OutEdgeList InEdgeList;
       
  2319         typedef OutEdgeIter InEdgeIter;
       
  2320         typedef OutEdgeIterCat InEdgeIterCat;
       
  2321         typedef OutEdgeIterDiff InEdgeIterDiff;
       
  2322 
       
  2323         typedef in_edge_iter<
       
  2324             InEdgeIter, vertex_descriptor, edge_descriptor, InEdgeIterDiff
       
  2325         > in_edge_iterator;
       
  2326 
       
  2327         typedef typename inv_adjacency_iterator_generator<graph_type,
       
  2328            vertex_descriptor, in_edge_iterator>::type inv_adjacency_iterator;
       
  2329 
       
  2330         // Edge Iterator
       
  2331 
       
  2332         typedef boost::detail::iterator_traits<EdgeIter> EdgeIterTraits;
       
  2333         typedef typename EdgeIterTraits::iterator_category EdgeIterCat;
       
  2334         typedef typename EdgeIterTraits::difference_type EdgeIterDiff;
       
  2335 
       
  2336         typedef undirected_edge_iter<
       
  2337             EdgeIter
       
  2338           , edge_descriptor
       
  2339           , EdgeIterDiff          
       
  2340         > UndirectedEdgeIter; // also used for bidirectional
       
  2341 
       
  2342         typedef adj_list_edge_iterator<vertex_iterator, out_edge_iterator, 
       
  2343            graph_type> DirectedEdgeIter;
       
  2344 
       
  2345         typedef typename boost::ct_if_t<on_edge_storage,
       
  2346           DirectedEdgeIter, UndirectedEdgeIter>::type edge_iterator;
       
  2347 
       
  2348         // stored_vertex and StoredVertexList
       
  2349         typedef typename container_gen<VertexListS, vertex_ptr>::type
       
  2350           SeqStoredVertexList;
       
  2351         struct seq_stored_vertex {
       
  2352           seq_stored_vertex() { }
       
  2353           seq_stored_vertex(const VertexProperty& p) : m_property(p) { }
       
  2354           OutEdgeList m_out_edges;
       
  2355           VertexProperty m_property;
       
  2356           typename SeqStoredVertexList::iterator m_position;
       
  2357         };
       
  2358         struct bidir_seq_stored_vertex {
       
  2359           bidir_seq_stored_vertex() { }
       
  2360           bidir_seq_stored_vertex(const VertexProperty& p) : m_property(p) { }
       
  2361           OutEdgeList m_out_edges;
       
  2362           InEdgeList m_in_edges;
       
  2363           VertexProperty m_property;
       
  2364           typename SeqStoredVertexList::iterator m_position;
       
  2365         };
       
  2366         struct rand_stored_vertex {
       
  2367           rand_stored_vertex() { }
       
  2368           rand_stored_vertex(const VertexProperty& p) : m_property(p) { }
       
  2369           OutEdgeList m_out_edges;
       
  2370           VertexProperty m_property;
       
  2371         };
       
  2372         struct bidir_rand_stored_vertex {
       
  2373           bidir_rand_stored_vertex() { }
       
  2374           bidir_rand_stored_vertex(const VertexProperty& p) : m_property(p) { }
       
  2375           OutEdgeList m_out_edges;
       
  2376           InEdgeList m_in_edges;
       
  2377           VertexProperty m_property;
       
  2378         };
       
  2379         typedef typename boost::ct_if_t<is_rand_access,
       
  2380           typename boost::ct_if_t<BidirectionalT,
       
  2381             bidir_rand_stored_vertex, rand_stored_vertex>::type,
       
  2382           typename boost::ct_if_t<BidirectionalT,
       
  2383             bidir_seq_stored_vertex, seq_stored_vertex>::type
       
  2384         >::type StoredVertex;
       
  2385         struct stored_vertex : public StoredVertex {
       
  2386           stored_vertex() { }
       
  2387           stored_vertex(const VertexProperty& p) : StoredVertex(p) { }
       
  2388         };
       
  2389 
       
  2390         typedef typename container_gen<VertexListS, stored_vertex>::type
       
  2391           RandStoredVertexList;
       
  2392         typedef typename boost::ct_if_t< is_rand_access,
       
  2393           RandStoredVertexList, SeqStoredVertexList>::type StoredVertexList;
       
  2394       }; // end of config
       
  2395 
       
  2396 
       
  2397       typedef typename boost::ct_if_t<BidirectionalT,
       
  2398         bidirectional_graph_helper_with_property<config>,
       
  2399         typename boost::ct_if_t<DirectedT,
       
  2400           directed_graph_helper<config>,
       
  2401           undirected_graph_helper<config>
       
  2402         >::type
       
  2403       >::type DirectedHelper;
       
  2404 
       
  2405       typedef typename boost::ct_if_t<is_rand_access,
       
  2406         vec_adj_list_impl<Graph, config, DirectedHelper>,
       
  2407         adj_list_impl<Graph, config, DirectedHelper>
       
  2408       >::type type;
       
  2409 
       
  2410     };
       
  2411 
       
  2412   } // namespace detail
       
  2413 
       
  2414     //=========================================================================
       
  2415     // Vertex Property Maps
       
  2416 
       
  2417     template <class Graph, class ValueType, class Reference, class Tag>
       
  2418     struct adj_list_vertex_property_map
       
  2419       : public boost::put_get_helper<
       
  2420           Reference,
       
  2421           adj_list_vertex_property_map<Graph, ValueType, Reference, Tag>
       
  2422         >
       
  2423     {
       
  2424       typedef typename Graph::stored_vertex StoredVertex;
       
  2425       typedef ValueType value_type;
       
  2426       typedef Reference reference;
       
  2427       typedef typename Graph::vertex_descriptor key_type;
       
  2428       typedef boost::lvalue_property_map_tag category;
       
  2429       inline adj_list_vertex_property_map() { }
       
  2430       inline adj_list_vertex_property_map(const Graph*) { }
       
  2431       inline Reference operator[](key_type v) const {
       
  2432         StoredVertex* sv = (StoredVertex*)v;
       
  2433         return get_property_value(sv->m_property, Tag());
       
  2434       }
       
  2435       inline Reference operator()(key_type v) const {
       
  2436         return this->operator[](v);
       
  2437       }
       
  2438     };
       
  2439 
       
  2440     template <class Graph, class Property, class PropRef>
       
  2441     struct adj_list_vertex_all_properties_map
       
  2442       : public boost::put_get_helper<PropRef,
       
  2443           adj_list_vertex_all_properties_map<Graph, Property, PropRef>
       
  2444         >
       
  2445     {
       
  2446       typedef typename Graph::stored_vertex StoredVertex;
       
  2447       typedef Property value_type;
       
  2448       typedef PropRef reference;
       
  2449       typedef typename Graph::vertex_descriptor key_type;
       
  2450       typedef boost::lvalue_property_map_tag category;
       
  2451       inline adj_list_vertex_all_properties_map() { }
       
  2452       inline adj_list_vertex_all_properties_map(const Graph*) { }
       
  2453       inline PropRef operator[](key_type v) const {
       
  2454         StoredVertex* sv = (StoredVertex*)v;
       
  2455         return sv->m_property;
       
  2456       }
       
  2457       inline PropRef operator()(key_type v) const {
       
  2458         return this->operator[](v);
       
  2459       }
       
  2460     };
       
  2461 
       
  2462     template <class Graph, class GraphPtr, class ValueType, class Reference,
       
  2463               class Tag>
       
  2464     struct vec_adj_list_vertex_property_map
       
  2465       : public boost::put_get_helper<
       
  2466           Reference,
       
  2467           vec_adj_list_vertex_property_map<Graph,GraphPtr,ValueType,Reference,
       
  2468              Tag>
       
  2469         >
       
  2470     {
       
  2471       typedef ValueType value_type;
       
  2472       typedef Reference reference;
       
  2473       typedef typename boost::graph_traits<Graph>::vertex_descriptor key_type;
       
  2474       typedef boost::lvalue_property_map_tag category;
       
  2475       vec_adj_list_vertex_property_map() { }
       
  2476       vec_adj_list_vertex_property_map(GraphPtr g) : m_g(g) { }
       
  2477       inline Reference operator[](key_type v) const {
       
  2478         return get_property_value(m_g->m_vertices[v].m_property,  Tag());
       
  2479       }
       
  2480       inline Reference operator()(key_type v) const {
       
  2481         return this->operator[](v);
       
  2482       }
       
  2483       GraphPtr m_g;
       
  2484     };
       
  2485 
       
  2486     template <class Graph, class GraphPtr, class Property, class PropertyRef>
       
  2487     struct vec_adj_list_vertex_all_properties_map
       
  2488       : public boost::put_get_helper<PropertyRef,
       
  2489           vec_adj_list_vertex_all_properties_map<Graph,GraphPtr,Property,
       
  2490             PropertyRef>
       
  2491         >
       
  2492     {
       
  2493       typedef Property value_type;
       
  2494       typedef PropertyRef reference;
       
  2495       typedef typename boost::graph_traits<Graph>::vertex_descriptor key_type;
       
  2496       typedef boost::lvalue_property_map_tag category;
       
  2497       vec_adj_list_vertex_all_properties_map() { }
       
  2498       vec_adj_list_vertex_all_properties_map(GraphPtr g) : m_g(g) { }
       
  2499       inline PropertyRef operator[](key_type v) const {
       
  2500         return m_g->m_vertices[v].m_property;
       
  2501       }
       
  2502       inline PropertyRef operator()(key_type v) const {
       
  2503         return this->operator[](v);
       
  2504       }
       
  2505       GraphPtr m_g;
       
  2506     };
       
  2507 
       
  2508     struct adj_list_any_vertex_pa {
       
  2509       template <class Tag, class Graph, class Property>
       
  2510       struct bind_ {
       
  2511         typedef typename property_value<Property, Tag>::type value_type;
       
  2512         typedef value_type& reference;
       
  2513         typedef const value_type& const_reference;
       
  2514 
       
  2515         typedef adj_list_vertex_property_map
       
  2516           <Graph, value_type, reference, Tag> type;
       
  2517         typedef adj_list_vertex_property_map
       
  2518           <Graph, value_type, const_reference, Tag> const_type;
       
  2519       };
       
  2520     };
       
  2521     struct adj_list_all_vertex_pa {
       
  2522       template <class Tag, class Graph, class Property>
       
  2523       struct bind_ {
       
  2524         typedef typename Graph::vertex_descriptor Vertex;
       
  2525         typedef adj_list_vertex_all_properties_map<Graph,Property,
       
  2526           Property&> type;
       
  2527         typedef adj_list_vertex_all_properties_map<Graph,Property,
       
  2528           const Property&> const_type;
       
  2529       };
       
  2530     };
       
  2531 
       
  2532     template <class Property, class Vertex>
       
  2533     struct vec_adj_list_vertex_id_map
       
  2534       : public boost::put_get_helper<
       
  2535           Vertex, vec_adj_list_vertex_id_map<Property, Vertex>
       
  2536         >
       
  2537     {
       
  2538       typedef Vertex value_type;
       
  2539       typedef Vertex key_type;
       
  2540       typedef Vertex reference;
       
  2541       typedef boost::readable_property_map_tag category;
       
  2542       inline vec_adj_list_vertex_id_map() { }
       
  2543       template <class Graph>
       
  2544       inline vec_adj_list_vertex_id_map(const Graph&) { }
       
  2545       inline value_type operator[](key_type v) const { return v; }
       
  2546       inline value_type operator()(key_type v) const { return v; }
       
  2547     };
       
  2548 
       
  2549     struct vec_adj_list_any_vertex_pa {
       
  2550       template <class Tag, class Graph, class Property>
       
  2551       struct bind_ {
       
  2552         typedef typename property_value<Property, Tag>::type value_type;
       
  2553         typedef value_type& reference;
       
  2554         typedef const value_type& const_reference;
       
  2555 
       
  2556         typedef vec_adj_list_vertex_property_map
       
  2557           <Graph, Graph*, value_type, reference, Tag> type;
       
  2558         typedef vec_adj_list_vertex_property_map
       
  2559           <Graph, const Graph*, value_type, const_reference, Tag> const_type;
       
  2560       };
       
  2561     };
       
  2562     struct vec_adj_list_id_vertex_pa {
       
  2563       template <class Tag, class Graph, class Property>
       
  2564       struct bind_ {
       
  2565         typedef typename Graph::vertex_descriptor Vertex;
       
  2566         typedef vec_adj_list_vertex_id_map<Property, Vertex> type;
       
  2567         typedef vec_adj_list_vertex_id_map<Property, Vertex> const_type;
       
  2568       };
       
  2569     };
       
  2570     struct vec_adj_list_all_vertex_pa {
       
  2571       template <class Tag, class Graph, class Property>
       
  2572       struct bind_ {
       
  2573         typedef typename Graph::vertex_descriptor Vertex;
       
  2574         typedef vec_adj_list_vertex_all_properties_map
       
  2575           <Graph, Graph*, Property, Property&> type;
       
  2576         typedef vec_adj_list_vertex_all_properties_map
       
  2577           <Graph, const Graph*, Property, const Property&> const_type;
       
  2578       };
       
  2579     };
       
  2580   namespace detail {
       
  2581     template <class Tag>
       
  2582     struct adj_list_choose_vertex_pa_helper {
       
  2583       typedef adj_list_any_vertex_pa type;
       
  2584     };
       
  2585     template <>
       
  2586     struct adj_list_choose_vertex_pa_helper<vertex_all_t> {
       
  2587       typedef adj_list_all_vertex_pa type;
       
  2588     };
       
  2589     template <class Tag, class Graph, class Property>
       
  2590     struct adj_list_choose_vertex_pa {
       
  2591       typedef typename adj_list_choose_vertex_pa_helper<Tag>::type Helper;
       
  2592       typedef typename Helper::template bind_<Tag,Graph,Property> Bind;
       
  2593       typedef typename Bind::type type;
       
  2594       typedef typename Bind::const_type const_type;
       
  2595     };
       
  2596 
       
  2597 
       
  2598     template <class Tag>
       
  2599     struct vec_adj_list_choose_vertex_pa_helper {
       
  2600       typedef vec_adj_list_any_vertex_pa type;
       
  2601     };
       
  2602     template <>
       
  2603     struct vec_adj_list_choose_vertex_pa_helper<vertex_index_t> {
       
  2604       typedef vec_adj_list_id_vertex_pa type;
       
  2605     };
       
  2606     template <>
       
  2607     struct vec_adj_list_choose_vertex_pa_helper<vertex_all_t> {
       
  2608       typedef vec_adj_list_all_vertex_pa type;
       
  2609     };
       
  2610     template <class Tag, class Graph, class Property>
       
  2611     struct vec_adj_list_choose_vertex_pa {
       
  2612       typedef typename vec_adj_list_choose_vertex_pa_helper<Tag>::type Helper;
       
  2613       typedef typename Helper::template bind_<Tag,Graph,Property> Bind;
       
  2614       typedef typename Bind::type type;
       
  2615       typedef typename Bind::const_type const_type;
       
  2616     };
       
  2617   } // namespace detail
       
  2618     
       
  2619     //=========================================================================
       
  2620     // Edge Property Map
       
  2621 
       
  2622     template <class Directed, class Value, class Ref, class Vertex,
       
  2623               class Property, class Tag>
       
  2624     struct adj_list_edge_property_map
       
  2625       : public put_get_helper< 
       
  2626           Ref,
       
  2627           adj_list_edge_property_map<Directed, Value, Ref, Vertex, Property, 
       
  2628             Tag>
       
  2629         >
       
  2630     {
       
  2631       typedef Value value_type;
       
  2632       typedef Ref reference;
       
  2633       typedef detail::edge_desc_impl<Directed, Vertex> key_type;
       
  2634       typedef boost::lvalue_property_map_tag category;
       
  2635       inline Ref operator[](key_type e) const {
       
  2636         Property& p = *(Property*)e.get_property();
       
  2637         return get_property_value(p, Tag());
       
  2638       }
       
  2639       inline Ref operator()(key_type e) const {
       
  2640         return this->operator[](e);
       
  2641       }
       
  2642     };
       
  2643 
       
  2644     template <class Directed, class Property, class PropRef, class PropPtr,
       
  2645       class Vertex>
       
  2646     struct adj_list_edge_all_properties_map
       
  2647       : public put_get_helper<PropRef,
       
  2648           adj_list_edge_all_properties_map<Directed, Property, PropRef, 
       
  2649             PropPtr, Vertex>
       
  2650         >
       
  2651     {
       
  2652       typedef Property value_type;
       
  2653       typedef PropRef reference;
       
  2654       typedef detail::edge_desc_impl<Directed, Vertex> key_type;
       
  2655       typedef boost::lvalue_property_map_tag category;
       
  2656       inline PropRef operator[](key_type e) const {
       
  2657         return *(PropPtr)e.get_property();
       
  2658       }
       
  2659       inline PropRef operator()(key_type e) const {
       
  2660         return this->operator[](e);
       
  2661       }
       
  2662     };
       
  2663 
       
  2664   // Edge Property Maps
       
  2665 
       
  2666   namespace detail {
       
  2667     struct adj_list_any_edge_pmap {
       
  2668       template <class Graph, class Property, class Tag>
       
  2669       struct bind_ {
       
  2670         typedef typename property_value<Property,Tag>::type value_type;
       
  2671         typedef value_type& reference;
       
  2672         typedef const value_type& const_reference;
       
  2673         
       
  2674         typedef adj_list_edge_property_map
       
  2675            <typename Graph::directed_category, value_type, reference, 
       
  2676             typename Graph::vertex_descriptor,Property,Tag> type;
       
  2677         typedef adj_list_edge_property_map
       
  2678            <typename Graph::directed_category, value_type, const_reference, 
       
  2679             typename Graph::vertex_descriptor,const Property, Tag> const_type;
       
  2680       };
       
  2681     };
       
  2682     struct adj_list_all_edge_pmap {
       
  2683       template <class Graph, class Property, class Tag>
       
  2684       struct bind_ {
       
  2685         typedef adj_list_edge_all_properties_map
       
  2686         <typename Graph::directed_category, Property, Property&, Property*,
       
  2687             typename Graph::vertex_descriptor> type;
       
  2688         typedef adj_list_edge_all_properties_map
       
  2689         <typename Graph::directed_category, Property, const Property&, 
       
  2690             const Property*, typename Graph::vertex_descriptor> const_type;
       
  2691       };
       
  2692     };
       
  2693 
       
  2694     template <class Tag>
       
  2695     struct adj_list_choose_edge_pmap_helper {
       
  2696       typedef adj_list_any_edge_pmap type;
       
  2697     };
       
  2698     template <>
       
  2699     struct adj_list_choose_edge_pmap_helper<edge_all_t> {
       
  2700       typedef adj_list_all_edge_pmap type;
       
  2701     };
       
  2702     template <class Tag, class Graph, class Property>
       
  2703     struct adj_list_choose_edge_pmap {
       
  2704       typedef typename adj_list_choose_edge_pmap_helper<Tag>::type Helper;
       
  2705       typedef typename Helper::template bind_<Graph,Property,Tag> Bind;
       
  2706       typedef typename Bind::type type;
       
  2707       typedef typename Bind::const_type const_type;
       
  2708     };
       
  2709     struct adj_list_edge_property_selector {
       
  2710       template <class Graph, class Property, class Tag>
       
  2711       struct bind_ {
       
  2712         typedef adj_list_choose_edge_pmap<Tag,Graph,Property> Choice;
       
  2713         typedef typename Choice::type type;
       
  2714         typedef typename Choice::const_type const_type;
       
  2715       };
       
  2716     };
       
  2717   } // namespace detail
       
  2718 
       
  2719   template <>  
       
  2720   struct edge_property_selector<adj_list_tag> {
       
  2721     typedef detail::adj_list_edge_property_selector type;
       
  2722   };
       
  2723   template <>  
       
  2724   struct edge_property_selector<vec_adj_list_tag> {
       
  2725     typedef detail::adj_list_edge_property_selector type;
       
  2726   };
       
  2727 
       
  2728   // Vertex Property Maps
       
  2729 
       
  2730   struct adj_list_vertex_property_selector {
       
  2731     template <class Graph, class Property, class Tag>
       
  2732     struct bind_ {
       
  2733       typedef detail::adj_list_choose_vertex_pa<Tag,Graph,Property> Choice;
       
  2734       typedef typename Choice::type type;
       
  2735       typedef typename Choice::const_type const_type;
       
  2736     };
       
  2737   };
       
  2738   template <>  
       
  2739   struct vertex_property_selector<adj_list_tag> {
       
  2740     typedef adj_list_vertex_property_selector type;
       
  2741   };
       
  2742 
       
  2743   struct vec_adj_list_vertex_property_selector {
       
  2744     template <class Graph, class Property, class Tag>
       
  2745     struct bind_ {
       
  2746       typedef detail::vec_adj_list_choose_vertex_pa<Tag,Graph,Property> Choice;
       
  2747       typedef typename Choice::type type;
       
  2748       typedef typename Choice::const_type const_type;
       
  2749     };
       
  2750   };
       
  2751   template <>  
       
  2752   struct vertex_property_selector<vec_adj_list_tag> {
       
  2753     typedef vec_adj_list_vertex_property_selector type;
       
  2754   };
       
  2755 
       
  2756 } // namespace boost
       
  2757 
       
  2758 #if !defined(BOOST_NO_HASH) && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
       
  2759 namespace BOOST_STD_EXTENSION_NAMESPACE {
       
  2760 
       
  2761   #if BOOST_WORKAROUND( _STLPORT_VERSION, >= 0x500 )
       
  2762   // STLport 5 already defines a hash<void*> specialization.
       
  2763   #else
       
  2764   template <>
       
  2765   struct hash< void* > // Need this when vertex_descriptor=void*
       
  2766   {
       
  2767     std::size_t
       
  2768     operator()(void* v) const { return (std::size_t)v; }
       
  2769   };
       
  2770   #endif
       
  2771 
       
  2772   template <typename V>
       
  2773   struct hash< boost::detail::stored_edge<V> > 
       
  2774   {
       
  2775     std::size_t
       
  2776     operator()(const boost::detail::stored_edge<V>& e) const
       
  2777     {
       
  2778       return hash<V>()(e.m_target);
       
  2779     }
       
  2780   };
       
  2781 
       
  2782   template <typename V, typename P>
       
  2783   struct hash< boost::detail::stored_edge_property <V,P> > 
       
  2784   {
       
  2785     std::size_t
       
  2786     operator()(const boost::detail::stored_edge_property<V,P>& e) const
       
  2787     {
       
  2788       return hash<V>()(e.m_target);
       
  2789     }
       
  2790   };
       
  2791 
       
  2792   template <typename V, typename I, typename P>
       
  2793   struct hash< boost::detail::stored_edge_iter<V,I, P> > 
       
  2794   {
       
  2795     std::size_t
       
  2796     operator()(const boost::detail::stored_edge_iter<V,I,P>& e) const
       
  2797     {
       
  2798       return hash<V>()(e.m_target);
       
  2799     }
       
  2800   };
       
  2801 
       
  2802 }
       
  2803 #endif
       
  2804 
       
  2805 
       
  2806 #undef stored_edge
       
  2807 #undef stored_edge_property
       
  2808 #undef stored_edge_iter
       
  2809 
       
  2810 #endif // BOOST_GRAPH_DETAIL_DETAIL_ADJACENCY_LIST_CCT
       
  2811 
       
  2812 /*
       
  2813   Implementation Notes:
       
  2814   
       
  2815   Many of the public interface functions in this file would have been
       
  2816   more conveniently implemented as inline friend functions.
       
  2817   However there are a few compiler bugs that make that approach
       
  2818   non-portable.
       
  2819  
       
  2820   1. g++ inline friend in namespace bug
       
  2821   2. g++ using clause doesn't work with inline friends
       
  2822   3. VC++ doesn't have Koenig lookup
       
  2823 
       
  2824   For these reasons, the functions were all written as non-inline free 
       
  2825   functions, and static cast was used to convert from the helper
       
  2826   class to the adjacency_list derived class.
       
  2827 
       
  2828   Looking back, it might have been better to write out all functions
       
  2829   in terms of the adjacency_list, and then use a tag to dispatch
       
  2830   to the various helpers instead of using inheritance.
       
  2831 
       
  2832  */