DriveHQ Start Menu
Cloud Drive Mapping
Folder Sync
Cloud Backup
True Drop Box
FTP/SFTP Hosting
Group Account
DriveHQ Start Menu
Online File Server
My Storage
|
Manage Shares
|
Publishes
|
Drop Boxes
|
Group Account
WebDAV Drive Mapping
Cloud Drive Home
|
WebDAV Guide
|
Drive Mapping Tool
|
Drive Mapping URL
Complete Data Backup
Backup Guide
|
Online Backup Tool
|
Cloud-to-Cloud Backup
FTP, Email & Web Service
FTP Home
|
FTP Hosting FAQ
|
Email Hosting
|
EmailManager
|
Web Hosting
Help & Resources
About
|
Enterprise Service
|
Partnership
|
Comparisons
|
Support
Quick Links
Security and Privacy
Download Software
Service Manual
Use Cases
Group Account
Online Help
Blog
Contact
Cloud Surveillance
Sign Up
Login
Features
Business Features
Online File Server
FTP Hosting
Cloud Drive Mapping
Cloud File Backup
Email Backup & Hosting
Cloud File Sharing
Folder Synchronization
Group Management
True Drop Box
Full-text Search
AD Integration/SSO
Mobile Access
IP Camera & DVR Solution
More...
Personal Features
Personal Cloud Drive
Backup All Devices
Mobile APPs
Personal Web Hosting
Sub-Account (for Kids)
Home/PC/Kids Monitoring
More...
Software
DriveHQ Drive Mapping Tool
DriveHQ FileManager
DriveHQ Online Backup
DriveHQ Mobile Apps
Pricing
Business Plans & Pricing
Personal Plans & Pricing
Price Comparison with Others
Feature Comparison with Others
Install Mobile App
Sign up
Creating account...
Invalid character in username! Only 0-9, a-z, A-Z, _, -, . allowed.
Username is required!
Invalid email address!
E-mail is required!
Password is required!
Password is invalid!
Password and confirmation do not match.
Confirm password is required!
I accept
Membership Agreement
Please read the Membership Agreement and check "I accept"!
Free Quick Sign-up
Sign-up Page
Log in
Signing in...
Username or e-mail address is required!
Password is required!
Keep me logged in
Quick Login
Forgot Password
Up
Upload
Download
Share
Publish
New Folder
New File
Copy
Cut
Delete
Paste
Rate
Upgrade
Rotate
Effect
Edit
Slide
History
// -*- c++ -*- //======================================================================= // Copyright 1997, 1998, 1999, 2000 University of Notre Dame. // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) //======================================================================= #ifndef BOOST_GRAPH_DETAIL_ADJACENCY_LIST_HPP #define BOOST_GRAPH_DETAIL_ADJACENCY_LIST_HPP #include
// for vertex_map in copy_impl #include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// Symbol truncation problems with MSVC, trying to shorten names. #define stored_edge se_ #define stored_edge_property sep_ #define stored_edge_iter sei_ /* Outline for this file: out_edge_iterator and in_edge_iterator implementation edge_iterator for undirected graph stored edge types (these object live in the out-edge/in-edge lists) directed edges helper class directed graph helper class undirected graph helper class bidirectional graph helper class bidirectional graph helper class (without edge properties) bidirectional graph helper class (with edge properties) adjacency_list helper class adj_list_impl class vec_adj_list_impl class adj_list_gen class vertex property map edge property map Note: it would be nice to merge some of the undirected and bidirectional code... it is awful similar. */ #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) // Stay out of the way of the concept checking class # define Graph Graph_ #endif namespace boost { namespace detail { template
struct directed_category_traits { typedef directed_tag directed_category; }; template <> struct directed_category_traits
{ typedef directed_tag directed_category; }; template <> struct directed_category_traits
{ typedef undirected_tag directed_category; }; template <> struct directed_category_traits
{ typedef bidirectional_tag directed_category; }; template
struct target_is { target_is(const Vertex& v) : m_target(v) { } template
bool operator()(const StoredEdge& e) const { return e.get_target() == m_target; } Vertex m_target; }; // O(E/V) template
void erase_from_incidence_list(EdgeList& el, vertex_descriptor v, allow_parallel_edge_tag) { boost::graph_detail::erase_if(el, detail::target_is
(v)); } // O(log(E/V)) template
void erase_from_incidence_list(EdgeList& el, vertex_descriptor v, disallow_parallel_edge_tag) { typedef typename EdgeList::value_type StoredEdge; el.erase(StoredEdge(v)); } //========================================================================= // Out-Edge and In-Edge Iterator Implementation template
struct out_edge_iter : iterator_adaptor< out_edge_iter
, BaseIter , EdgeDescriptor , use_default , EdgeDescriptor , Difference > { typedef iterator_adaptor< out_edge_iter
, BaseIter , EdgeDescriptor , use_default , EdgeDescriptor , Difference > super_t; inline out_edge_iter() { } inline out_edge_iter(const BaseIter& i, const VertexDescriptor& src) : super_t(i), m_src(src) { } inline EdgeDescriptor dereference() const { return EdgeDescriptor(m_src, (*this->base()).get_target(), &(*this->base()).get_property()); } VertexDescriptor m_src; }; template
struct in_edge_iter : iterator_adaptor< in_edge_iter
, BaseIter , EdgeDescriptor , use_default , EdgeDescriptor , Difference > { typedef iterator_adaptor< in_edge_iter
, BaseIter , EdgeDescriptor , use_default , EdgeDescriptor , Difference > super_t; inline in_edge_iter() { } inline in_edge_iter(const BaseIter& i, const VertexDescriptor& src) : super_t(i), m_src(src) { } inline EdgeDescriptor dereference() const { return EdgeDescriptor((*this->base()).get_target(), m_src, &this->base()->get_property()); } VertexDescriptor m_src; }; //========================================================================= // Undirected Edge Iterator Implementation template
struct undirected_edge_iter : iterator_adaptor< undirected_edge_iter
, EdgeIter , EdgeDescriptor , use_default , EdgeDescriptor , Difference > { typedef iterator_adaptor< undirected_edge_iter
, EdgeIter , EdgeDescriptor , use_default , EdgeDescriptor , Difference > super_t; undirected_edge_iter() {} explicit undirected_edge_iter(EdgeIter i) : super_t(i) {} inline EdgeDescriptor dereference() const { return EdgeDescriptor( (*this->base()).m_source , (*this->base()).m_target , &this->base()->get_property()); } }; //========================================================================= // Edge Storage Types (stored in the out-edge/in-edge lists) template
class stored_edge : public boost::equality_comparable1< stored_edge
, boost::less_than_comparable1< stored_edge
> > { public: typedef no_property property_type; inline stored_edge() { } inline stored_edge(Vertex target, const no_property& = no_property()) : m_target(target) { } // Need to write this explicitly so stored_edge_property can // invoke Base::operator= (at least, for SGI MIPSPro compiler) inline stored_edge& operator=(const stored_edge& x) { m_target = x.m_target; return *this; } inline Vertex& get_target() const { return m_target; } inline const no_property& get_property() const { return s_prop; } inline bool operator==(const stored_edge& x) const { return m_target == x.get_target(); } inline bool operator<(const stored_edge& x) const { return m_target < x.get_target(); } //protected: need to add hash<> as a friend static no_property s_prop; // Sometimes target not used as key in the set, and in that case // it is ok to change the target. mutable Vertex m_target; }; template
no_property stored_edge
::s_prop; template
class stored_edge_property : public stored_edge
{ typedef stored_edge_property self; typedef stored_edge
Base; public: typedef Property property_type; inline stored_edge_property() { } inline stored_edge_property(Vertex target, const Property& p = Property()) : stored_edge
(target), m_property(new Property(p)) { } stored_edge_property(const self& x) : Base(x), m_property(const_cast
(x).m_property) { } self& operator=(const self& x) { Base::operator=(x); m_property = const_cast
(x).m_property; return *this; } inline Property& get_property() { return *m_property; } inline const Property& get_property() const { return *m_property; } protected: // Holding the property by-value causes edge-descriptor // invalidation for add_edge() with EdgeList=vecS. Instead we // hold a pointer to the property. std::auto_ptr is not // a perfect fit for the job, but it is darn close. std::auto_ptr
m_property; }; template
class stored_edge_iter : public stored_edge
{ public: typedef Property property_type; inline stored_edge_iter() { } inline stored_edge_iter(Vertex v) : stored_edge
(v) { } inline stored_edge_iter(Vertex v, Iter i, void* = 0) : stored_edge
(v), m_iter(i) { } inline Property& get_property() { return m_iter->get_property(); } inline const Property& get_property() const { return m_iter->get_property(); } inline Iter get_iter() const { return m_iter; } protected: Iter m_iter; }; // For when the EdgeList is a std::vector. // Want to make the iterator stable, so use an offset // instead of an iterator into a std::vector template
class stored_ra_edge_iter : public stored_edge
{ typedef typename EdgeVec::iterator Iter; public: typedef Property property_type; inline stored_ra_edge_iter() { } inline stored_ra_edge_iter(Vertex v, Iter i = Iter(), EdgeVec* edge_vec = 0) : stored_edge
(v), m_i(i - edge_vec->begin()), m_vec(edge_vec){ } inline Property& get_property() { return (*m_vec)[m_i].get_property(); } inline const Property& get_property() const { return (*m_vec)[m_i].get_property(); } inline Iter get_iter() const { return m_vec->begin() + m_i; } protected: std::size_t m_i; EdgeVec* m_vec; }; } // namespace detail template
const typename property_value
::type& get(Tag property_tag, const detail::stored_edge_property
& e) { return get_property_value(e.get_property(), property_tag); } template
const typename property_value
::type& get(Tag property_tag, const detail::stored_edge_iter
& e) { return get_property_value(e.get_property(), property_tag); } template
const typename property_value
::type& get(Tag property_tag, const detail::stored_ra_edge_iter
& e) { return get_property_value(e.get_property(), property_tag); } //========================================================================= // Directed Edges Helper Class namespace detail { // O(E/V) template
inline void remove_directed_edge_dispatch(edge_descriptor, EdgeList& el, StoredProperty& p) { for (typename EdgeList::iterator i = el.begin(); i != el.end(); ++i) if (&(*i).get_property() == &p) { el.erase(i); return; } } template
inline void remove_directed_edge_if_dispatch(incidence_iterator first, incidence_iterator last, EdgeList& el, Predicate pred, boost::allow_parallel_edge_tag) { // remove_if while (first != last && !pred(*first)) ++first; incidence_iterator i = first; if (first != last) for (; i != last; ++i) if (!pred(*i)) { *first.base() = *i.base(); ++first; } el.erase(first.base(), el.end()); } template
inline void remove_directed_edge_if_dispatch(incidence_iterator first, incidence_iterator last, EdgeList& el, Predicate pred, boost::disallow_parallel_edge_tag) { for (incidence_iterator next = first; first != last; first = next) { ++next; if (pred(*first)) el.erase( first.base() ); } } template
inline void undirected_remove_out_edge_if_dispatch(Graph& g, incidence_iterator first, incidence_iterator last, EdgeList& el, Predicate pred, boost::allow_parallel_edge_tag) { typedef typename Graph::global_edgelist_selector EdgeListS; BOOST_STATIC_ASSERT((!is_same
::value)); // remove_if while (first != last && !pred(*first)) ++first; incidence_iterator i = first; bool self_loop_removed = false; if (first != last) for (; i != last; ++i) { if (self_loop_removed) { /* With self loops, the descriptor will show up * twice. The first time it will be removed, and now it * will be skipped. */ self_loop_removed = false; } else if (!pred(*i)) { *first.base() = *i.base(); ++first; } else { if (source(*i, g) == target(*i, g)) self_loop_removed = true; else { // Remove the edge from the target detail::remove_directed_edge_dispatch (*i, g.out_edge_list(target(*i, g)), *(PropT*)(*i).get_property()); } // Erase the edge property g.m_edges.erase( (*i.base()).get_iter() ); } } el.erase(first.base(), el.end()); } template
inline void undirected_remove_out_edge_if_dispatch(Graph& g, incidence_iterator first, incidence_iterator last, EdgeList& el, Predicate pred, boost::disallow_parallel_edge_tag) { typedef typename Graph::global_edgelist_selector EdgeListS; BOOST_STATIC_ASSERT((!is_same
::value)); for (incidence_iterator next = first; first != last; first = next) { ++next; if (pred(*first)) { if (source(*first, g) != target(*first, g)) { // Remove the edge from the target detail::remove_directed_edge_dispatch (*first, g.out_edge_list(target(*first, g)), *(PropT*)(*first).get_property()); } // Erase the edge property g.m_edges.erase( (*first.base()).get_iter() ); // Erase the edge in the source el.erase( first.base() ); } } } // O(E/V) template
inline void remove_directed_edge_dispatch(edge_descriptor e, EdgeList& el, no_property&) { for (typename EdgeList::iterator i = el.begin(); i != el.end(); ++i) if ((*i).get_target() == e.m_target) { el.erase(i); return; } } } // namespace detail template
struct directed_edges_helper { // Placement of these overloaded remove_edge() functions // inside the class avoids a VC++ bug. // O(E/V) inline void remove_edge(typename Config::edge_descriptor e) { typedef typename Config::graph_type graph_type; graph_type& g = static_cast
(*this); typename Config::OutEdgeList& el = g.out_edge_list(source(e, g)); typedef typename Config::OutEdgeList::value_type::property_type PType; detail::remove_directed_edge_dispatch(e, el, *(PType*)e.get_property()); } // O(1) inline void remove_edge(typename Config::out_edge_iterator iter) { typedef typename Config::graph_type graph_type; graph_type& g = static_cast
(*this); typename Config::edge_descriptor e = *iter; typename Config::OutEdgeList& el = g.out_edge_list(source(e, g)); el.erase(iter.base()); } }; // O(1) template
inline std::pair
edges(const directed_edges_helper
& g_) { typedef typename Config::graph_type graph_type; typedef typename Config::edge_iterator edge_iterator; const graph_type& cg = static_cast
(g_); graph_type& g = const_cast
(cg); return std::make_pair( edge_iterator(g.vertex_set().begin(), g.vertex_set().begin(), g.vertex_set().end(), g), edge_iterator(g.vertex_set().begin(), g.vertex_set().end(), g.vertex_set().end(), g) ); } //========================================================================= // Directed Graph Helper Class struct adj_list_dir_traversal_tag : public virtual vertex_list_graph_tag, public virtual incidence_graph_tag, public virtual adjacency_graph_tag, public virtual edge_list_graph_tag { }; template
struct directed_graph_helper : public directed_edges_helper
{ typedef typename Config::edge_descriptor edge_descriptor; typedef adj_list_dir_traversal_tag traversal_category; }; // O(E/V) template
inline void remove_edge(typename Config::vertex_descriptor u, typename Config::vertex_descriptor v, directed_graph_helper
& g_) { typedef typename Config::graph_type graph_type; typedef typename Config::edge_parallel_category Cat; graph_type& g = static_cast
(g_); detail::erase_from_incidence_list(g.out_edge_list(u), v, Cat()); } template
inline void remove_out_edge_if(typename Config::vertex_descriptor u, Predicate pred, directed_graph_helper
& g_) { typedef typename Config::graph_type graph_type; graph_type& g = static_cast
(g_); typename Config::out_edge_iterator first, last; tie(first, last) = out_edges(u, g); typedef typename Config::edge_parallel_category edge_parallel_category; detail::remove_directed_edge_if_dispatch (first, last, g.out_edge_list(u), pred, edge_parallel_category()); } template
inline void remove_edge_if(Predicate pred, directed_graph_helper
& g_) { typedef typename Config::graph_type graph_type; graph_type& g = static_cast
(g_); typename Config::vertex_iterator vi, vi_end; for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) remove_out_edge_if(*vi, pred, g); } template
inline void remove_edge(EdgeOrIter e_or_iter, directed_graph_helper
& g_) { g_.remove_edge(e_or_iter); } // O(V + E) for allow_parallel_edges // O(V * log(E/V)) for disallow_parallel_edges template
inline void clear_vertex(typename Config::vertex_descriptor u, directed_graph_helper
& g_) { typedef typename Config::graph_type graph_type; typedef typename Config::edge_parallel_category Cat; graph_type& g = static_cast
(g_); typename Config::vertex_iterator vi, viend; for (boost::tie(vi, viend) = vertices(g); vi != viend; ++vi) detail::erase_from_incidence_list(g.out_edge_list(*vi), u, Cat()); g.out_edge_list(u).clear(); // clear() should be a req of Sequence and AssociativeContainer, // or maybe just Container } template
inline void clear_out_edges(typename Config::vertex_descriptor u, directed_graph_helper
& g_) { typedef typename Config::graph_type graph_type; typedef typename Config::edge_parallel_category Cat; graph_type& g = static_cast
(g_); g.out_edge_list(u).clear(); // clear() should be a req of Sequence and AssociativeContainer, // or maybe just Container } // O(V), could do better... template
inline typename Config::edges_size_type num_edges(const directed_graph_helper
& g_) { typedef typename Config::graph_type graph_type; const graph_type& g = static_cast
(g_); typename Config::edges_size_type num_e = 0; typename Config::vertex_iterator vi, vi_end; for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) num_e += out_degree(*vi, g); return num_e; } // O(1) for allow_parallel_edge_tag // O(log(E/V)) for disallow_parallel_edge_tag template
inline std::pair
::edge_descriptor, bool> add_edge(typename Config::vertex_descriptor u, typename Config::vertex_descriptor v, const typename Config::edge_property_type& p, directed_graph_helper
& g_) { typedef typename Config::edge_descriptor edge_descriptor; typedef typename Config::graph_type graph_type; typedef typename Config::StoredEdge StoredEdge; graph_type& g = static_cast
(g_); typename Config::OutEdgeList::iterator i; bool inserted; boost::tie(i, inserted) = boost::graph_detail::push(g.out_edge_list(u), StoredEdge(v, p)); return std::make_pair(edge_descriptor(u, v, &(*i).get_property()), inserted); } // Did not use default argument here because that // causes Visual C++ to get confused. template
inline std::pair
add_edge(typename Config::vertex_descriptor u, typename Config::vertex_descriptor v, directed_graph_helper
& g_) { typename Config::edge_property_type p; return add_edge(u, v, p, g_); } //========================================================================= // Undirected Graph Helper Class template
struct undirected_graph_helper; struct undir_adj_list_traversal_tag : public virtual vertex_list_graph_tag, public virtual incidence_graph_tag, public virtual adjacency_graph_tag, public virtual edge_list_graph_tag, public virtual bidirectional_graph_tag { }; namespace detail { // using class with specialization for dispatch is a VC++ workaround. template
struct remove_undirected_edge_dispatch { // O(E/V) template
static void apply(edge_descriptor e, undirected_graph_helper
& g_, StoredProperty& p) { typedef typename Config::global_edgelist_selector EdgeListS; BOOST_STATIC_ASSERT((!is_same
::value)); typedef typename Config::graph_type graph_type; graph_type& g = static_cast
(g_); typename Config::OutEdgeList& out_el = g.out_edge_list(source(e, g)); typename Config::OutEdgeList::iterator out_i = out_el.begin(); for (; out_i != out_el.end(); ++out_i) if (&(*out_i).get_property() == &p) { out_el.erase(out_i); break; } typename Config::OutEdgeList& in_el = g.out_edge_list(target(e, g)); typename Config::OutEdgeList::iterator in_i = in_el.begin(); for (; in_i != in_el.end(); ++in_i) if (&(*in_i).get_property() == &p) { g.m_edges.erase((*in_i).get_iter()); in_el.erase(in_i); return; } } }; template <> struct remove_undirected_edge_dispatch
{ // O(E/V) template
static void apply(edge_descriptor e, undirected_graph_helper
& g_, no_property&) { typedef typename Config::global_edgelist_selector EdgeListS; BOOST_STATIC_ASSERT((!is_same
::value)); typedef typename Config::graph_type graph_type; graph_type& g = static_cast
(g_); no_property* p = (no_property*)e.get_property(); typename Config::OutEdgeList& out_el = g.out_edge_list(source(e, g)); typename Config::OutEdgeList::iterator out_i = out_el.begin(); for (; out_i != out_el.end(); ++out_i) if (&(*out_i).get_property() == p) { out_el.erase(out_i); break; } typename Config::OutEdgeList& in_el = g.out_edge_list(target(e, g)); typename Config::OutEdgeList::iterator in_i = in_el.begin(); for (; in_i != in_el.end(); ++in_i) if (&(*in_i).get_property() == p) { g.m_edges.erase((*in_i).get_iter()); in_el.erase(in_i); return; } } }; // O(E/V) template
inline void remove_edge_and_property(Graph& g, EdgeList& el, Vertex v, boost::allow_parallel_edge_tag cat) { typedef typename Graph::global_edgelist_selector EdgeListS; BOOST_STATIC_ASSERT((!is_same
::value)); typedef typename EdgeList::value_type StoredEdge; typename EdgeList::iterator i = el.begin(), end = el.end(); for (; i != end; ++i) if ((*i).get_target() == v) g.m_edges.erase((*i).get_iter()); detail::erase_from_incidence_list(el, v, cat); } // O(log(E/V)) template
inline void remove_edge_and_property(Graph& g, EdgeList& el, Vertex v, boost::disallow_parallel_edge_tag) { typedef typename Graph::global_edgelist_selector EdgeListS; BOOST_STATIC_ASSERT((!is_same
::value)); typedef typename EdgeList::value_type StoredEdge; typename EdgeList::iterator i = el.find(StoredEdge(v)), end = el.end(); if (i != end) { g.m_edges.erase((*i).get_iter()); el.erase(i); } } } // namespace detail template
struct list_edge // short name due to VC++ truncation and linker problems : public boost::detail::edge_base
{ typedef EdgeProperty property_type; typedef boost::detail::edge_base
Base; list_edge(Vertex u, Vertex v, const EdgeProperty& p = EdgeProperty()) : Base(u, v), m_property(p) { } EdgeProperty& get_property() { return m_property; } const EdgeProperty& get_property() const { return m_property; } // the following methods should never be used, but are needed // to make SGI MIPSpro C++ happy list_edge() { } bool operator==(const list_edge&) const { return false; } bool operator<(const list_edge&) const { return false; } EdgeProperty m_property; }; template
struct undirected_graph_helper { typedef undir_adj_list_traversal_tag traversal_category; // Placement of these overloaded remove_edge() functions // inside the class avoids a VC++ bug. // O(E/V) inline void remove_edge(typename Config::edge_descriptor e) { typedef typename Config::global_edgelist_selector EdgeListS; BOOST_STATIC_ASSERT((!is_same
::value)); typedef typename Config::OutEdgeList::value_type::property_type PType; detail::remove_undirected_edge_dispatch
::apply (e, *this, *(PType*)e.get_property()); } // O(E/V) inline void remove_edge(typename Config::out_edge_iterator iter) { this->remove_edge(*iter); } }; // Had to make these non-members to avoid accidental instantiation // on SGI MIPSpro C++ template
inline typename C::InEdgeList& in_edge_list(undirected_graph_helper
&, typename C::vertex_descriptor v) { typename C::stored_vertex* sv = (typename C::stored_vertex*)v; return sv->m_out_edges; } template
inline const typename C::InEdgeList& in_edge_list(const undirected_graph_helper
&, typename C::vertex_descriptor v) { typename C::stored_vertex* sv = (typename C::stored_vertex*)v; return sv->m_out_edges; } // O(E/V) template
inline void remove_edge(EdgeOrIter e, undirected_graph_helper
& g_) { typedef typename Config::global_edgelist_selector EdgeListS; BOOST_STATIC_ASSERT((!is_same
::value)); g_.remove_edge(e); } // O(E/V) or O(log(E/V)) template
void remove_edge(typename Config::vertex_descriptor u, typename Config::vertex_descriptor v, undirected_graph_helper
& g_) { typedef typename Config::global_edgelist_selector EdgeListS; BOOST_STATIC_ASSERT((!is_same
::value)); typedef typename Config::graph_type graph_type; graph_type& g = static_cast
(g_); typedef typename Config::edge_parallel_category Cat; detail::remove_edge_and_property(g, g.out_edge_list(u), v, Cat()); detail::erase_from_incidence_list(g.out_edge_list(v), u, Cat()); } template
void remove_out_edge_if(typename Config::vertex_descriptor u, Predicate pred, undirected_graph_helper
& g_) { typedef typename Config::global_edgelist_selector EdgeListS; BOOST_STATIC_ASSERT((!is_same
::value)); typedef typename Config::graph_type graph_type; typedef typename Config::OutEdgeList::value_type::property_type PropT; graph_type& g = static_cast
(g_); typename Config::out_edge_iterator first, last; tie(first, last) = out_edges(u, g); typedef typename Config::edge_parallel_category Cat; detail::undirected_remove_out_edge_if_dispatch
(g, first, last, g.out_edge_list(u), pred, Cat()); } template
void remove_in_edge_if(typename Config::vertex_descriptor u, Predicate pred, undirected_graph_helper
& g_) { typedef typename Config::global_edgelist_selector EdgeListS; BOOST_STATIC_ASSERT((!is_same
::value)); remove_out_edge_if(u, pred, g_); } // O(E/V * E) or O(log(E/V) * E) template
void remove_edge_if(Predicate pred, undirected_graph_helper
& g_) { typedef typename Config::global_edgelist_selector EdgeListS; BOOST_STATIC_ASSERT((!is_same
::value)); typedef typename Config::graph_type graph_type; graph_type& g = static_cast
(g_); typename Config::edge_iterator ei, ei_end, next; tie(ei, ei_end) = edges(g); for (next = ei; ei != ei_end; ei = next) { ++next; if (pred(*ei)) remove_edge(*ei, g); } } // O(1) template
inline std::pair
edges(const undirected_graph_helper
& g_) { typedef typename Config::graph_type graph_type; typedef typename Config::edge_iterator edge_iterator; const graph_type& cg = static_cast
(g_); graph_type& g = const_cast
(cg); return std::make_pair( edge_iterator(g.m_edges.begin()), edge_iterator(g.m_edges.end()) ); } // O(1) template
inline typename Config::edges_size_type num_edges(const undirected_graph_helper
& g_) { typedef typename Config::graph_type graph_type; const graph_type& g = static_cast
(g_); return g.m_edges.size(); } // O(E/V * E/V) template
inline void clear_vertex(typename Config::vertex_descriptor u, undirected_graph_helper
& g_) { typedef typename Config::global_edgelist_selector EdgeListS; BOOST_STATIC_ASSERT((!is_same
::value)); typedef typename Config::graph_type graph_type; typedef typename Config::edge_parallel_category Cat; graph_type& g = static_cast
(g_); typename Config::OutEdgeList& el = g.out_edge_list(u); typename Config::OutEdgeList::iterator ei = el.begin(), ei_end = el.end(); for (; ei != ei_end; ++ei) { detail::erase_from_incidence_list (g.out_edge_list((*ei).get_target()), u, Cat()); g.m_edges.erase((*ei).get_iter()); } g.out_edge_list(u).clear(); } // O(1) for allow_parallel_edge_tag // O(log(E/V)) for disallow_parallel_edge_tag template
inline std::pair
add_edge(typename Config::vertex_descriptor u, typename Config::vertex_descriptor v, const typename Config::edge_property_type& p, undirected_graph_helper
& g_) { typedef typename Config::StoredEdge StoredEdge; typedef typename Config::edge_descriptor edge_descriptor; typedef typename Config::graph_type graph_type; graph_type& g = static_cast
(g_); bool inserted; typename Config::EdgeContainer::value_type e(u, v, p); typename Config::EdgeContainer::iterator p_iter = graph_detail::push(g.m_edges, e).first; typename Config::OutEdgeList::iterator i; boost::tie(i, inserted) = boost::graph_detail::push(g.out_edge_list(u), StoredEdge(v, p_iter, &g.m_edges)); if (inserted) { boost::graph_detail::push(g.out_edge_list(v), StoredEdge(u, p_iter, &g.m_edges)); return std::make_pair(edge_descriptor(u, v, &p_iter->get_property()), true); } else { g.m_edges.erase(p_iter); return std::make_pair (edge_descriptor(u, v, &i->get_iter()->get_property()), false); } } template
inline std::pair
add_edge(typename Config::vertex_descriptor u, typename Config::vertex_descriptor v, undirected_graph_helper
& g_) { typename Config::edge_property_type p; return add_edge(u, v, p, g_); } // O(1) template
inline typename Config::degree_size_type degree(typename Config::vertex_descriptor u, const undirected_graph_helper
& g_) { typedef typename Config::graph_type Graph; const Graph& g = static_cast
(g_); return out_degree(u, g); } template
inline std::pair
in_edges(typename Config::vertex_descriptor u, const undirected_graph_helper
& g_) { typedef typename Config::graph_type Graph; const Graph& cg = static_cast
(g_); Graph& g = const_cast
(cg); typedef typename Config::in_edge_iterator in_edge_iterator; return std::make_pair(in_edge_iterator(g.out_edge_list(u).begin(), u), in_edge_iterator(g.out_edge_list(u).end(), u)); } template
inline typename Config::degree_size_type in_degree(typename Config::vertex_descriptor u, const undirected_graph_helper
& g_) { return degree(u, g_); } //========================================================================= // Bidirectional Graph Helper Class struct bidir_adj_list_traversal_tag : public virtual vertex_list_graph_tag, public virtual incidence_graph_tag, public virtual adjacency_graph_tag, public virtual edge_list_graph_tag, public virtual bidirectional_graph_tag { }; template
struct bidirectional_graph_helper : public directed_edges_helper
{ typedef bidir_adj_list_traversal_tag traversal_category; }; // Had to make these non-members to avoid accidental instantiation // on SGI MIPSpro C++ template
inline typename C::InEdgeList& in_edge_list(bidirectional_graph_helper
&, typename C::vertex_descriptor v) { typename C::stored_vertex* sv = (typename C::stored_vertex*)v; return sv->m_in_edges; } template
inline const typename C::InEdgeList& in_edge_list(const bidirectional_graph_helper
&, typename C::vertex_descriptor v) { typename C::stored_vertex* sv = (typename C::stored_vertex*)v; return sv->m_in_edges; } template
inline void remove_edge_if(Predicate pred, bidirectional_graph_helper
& g_) { typedef typename Config::global_edgelist_selector EdgeListS; BOOST_STATIC_ASSERT((!is_same
::value)); typedef typename Config::graph_type graph_type; graph_type& g = static_cast
(g_); typename Config::edge_iterator ei, ei_end, next; tie(ei, ei_end) = edges(g); for (next = ei; ei != ei_end; ei = next) { ++next; if (pred(*ei)) remove_edge(*ei, g); } } template
inline std::pair
in_edges(typename Config::vertex_descriptor u, const bidirectional_graph_helper
& g_) { typedef typename Config::graph_type graph_type; const graph_type& cg = static_cast
(g_); graph_type& g = const_cast
(cg); typedef typename Config::in_edge_iterator in_edge_iterator; return std::make_pair(in_edge_iterator(in_edge_list(g, u).begin(), u), in_edge_iterator(in_edge_list(g, u).end(), u)); } // O(1) template
inline std::pair
edges(const bidirectional_graph_helper
& g_) { typedef typename Config::graph_type graph_type; typedef typename Config::edge_iterator edge_iterator; const graph_type& cg = static_cast
(g_); graph_type& g = const_cast
(cg); return std::make_pair( edge_iterator(g.m_edges.begin()), edge_iterator(g.m_edges.end()) ); } //========================================================================= // Bidirectional Graph Helper Class (with edge properties) template
struct bidirectional_graph_helper_with_property : public bidirectional_graph_helper
{ typedef typename Config::graph_type graph_type; typedef typename Config::out_edge_iterator out_edge_iterator; std::pair
get_parallel_edge_sublist(typename Config::edge_descriptor e, const graph_type& g, void*) { return out_edges(source(e, g), g); } std::pair
get_parallel_edge_sublist(typename Config::edge_descriptor e, const graph_type& g, setS*) { return edge_range(source(e, g), target(e, g), g); } std::pair
get_parallel_edge_sublist(typename Config::edge_descriptor e, const graph_type& g, multisetS*) { return edge_range(source(e, g), target(e, g), g); } #if !defined BOOST_NO_HASH std::pair
get_parallel_edge_sublist(typename Config::edge_descriptor e, const graph_type& g, hash_setS*) { return edge_range(source(e, g), target(e, g), g); } #endif // Placement of these overloaded remove_edge() functions // inside the class avoids a VC++ bug. // O(E/V) or O(log(E/V)) void remove_edge(typename Config::edge_descriptor e) { typedef typename Config::global_edgelist_selector EdgeListS; BOOST_STATIC_ASSERT((!is_same
::value)); graph_type& g = static_cast
(*this); typedef typename Config::edgelist_selector OutEdgeListS; std::pair
rng = get_parallel_edge_sublist(e, g, (OutEdgeListS*)(0)); rng.first = std::find(rng.first, rng.second, e); assert(rng.first != rng.second); remove_edge(rng.first); } inline void remove_edge(typename Config::out_edge_iterator iter) { typedef typename Config::global_edgelist_selector EdgeListS; BOOST_STATIC_ASSERT((!is_same
::value)); typedef typename Config::graph_type graph_type; graph_type& g = static_cast
(*this); typename Config::edge_descriptor e = *iter; typename Config::OutEdgeList& oel = g.out_edge_list(source(e, g)); typename Config::InEdgeList& iel = in_edge_list(g, target(e, g)); typedef typename Config::OutEdgeList::value_type::property_type PType; PType& p = *(PType*)e.get_property(); detail::remove_directed_edge_dispatch(*iter, iel, p); g.m_edges.erase(iter.base()->get_iter()); oel.erase(iter.base()); } }; // O(E/V) for allow_parallel_edge_tag // O(log(E/V)) for disallow_parallel_edge_tag template
inline void remove_edge(typename Config::vertex_descriptor u, typename Config::vertex_descriptor v, bidirectional_graph_helper_with_property
& g_) { typedef typename Config::global_edgelist_selector EdgeListS; BOOST_STATIC_ASSERT((!is_same
::value)); typedef typename Config::graph_type graph_type; graph_type& g = static_cast
(g_); typedef typename Config::edge_parallel_category Cat; detail::remove_edge_and_property(g, g.out_edge_list(u), v, Cat()); detail::erase_from_incidence_list(in_edge_list(g, v), u, Cat()); } // O(E/V) or O(log(E/V)) template
inline void remove_edge(EdgeOrIter e, bidirectional_graph_helper_with_property
& g_) { typedef typename Config::global_edgelist_selector EdgeListS; BOOST_STATIC_ASSERT((!is_same
::value)); g_.remove_edge(e); } template
inline void remove_out_edge_if(typename Config::vertex_descriptor u, Predicate pred, bidirectional_graph_helper_with_property
& g_) { typedef typename Config::global_edgelist_selector EdgeListS; BOOST_STATIC_ASSERT((!is_same
::value)); typedef typename Config::graph_type graph_type; typedef typename Config::OutEdgeList::value_type::property_type PropT; graph_type& g = static_cast
(g_); typedef typename Config::EdgeIter EdgeIter; typedef std::vector
Garbage; Garbage garbage; // First remove the edges from the targets' in-edge lists and // from the graph's edge set list. typename Config::out_edge_iterator out_i, out_end; for (tie(out_i, out_end) = out_edges(u, g); out_i != out_end; ++out_i) if (pred(*out_i)) { detail::remove_directed_edge_dispatch (*out_i, in_edge_list(g, target(*out_i, g)), *(PropT*)(*out_i).get_property()); // Put in garbage to delete later. Will need the properties // for the remove_if of the out-edges. garbage.push_back((*out_i.base()).get_iter()); } // Now remove the edges from this out-edge list. typename Config::out_edge_iterator first, last; tie(first, last) = out_edges(u, g); typedef typename Config::edge_parallel_category Cat; detail::remove_directed_edge_if_dispatch (first, last, g.out_edge_list(u), pred, Cat()); // Now delete the edge properties from the g.m_edges list for (typename Garbage::iterator i = garbage.begin(); i != garbage.end(); ++i) g.m_edges.erase(*i); } template
inline void remove_in_edge_if(typename Config::vertex_descriptor v, Predicate pred, bidirectional_graph_helper_with_property
& g_) { typedef typename Config::global_edgelist_selector EdgeListS; BOOST_STATIC_ASSERT((!is_same
::value)); typedef typename Config::graph_type graph_type; typedef typename Config::OutEdgeList::value_type::property_type PropT; graph_type& g = static_cast
(g_); typedef typename Config::EdgeIter EdgeIter; typedef std::vector
Garbage; Garbage garbage; // First remove the edges from the sources' out-edge lists and // from the graph's edge set list. typename Config::in_edge_iterator in_i, in_end; for (tie(in_i, in_end) = in_edges(v, g); in_i != in_end; ++in_i) if (pred(*in_i)) { typename Config::vertex_descriptor u = source(*in_i, g); detail::remove_directed_edge_dispatch (*in_i, g.out_edge_list(u), *(PropT*)(*in_i).get_property()); // Put in garbage to delete later. Will need the properties // for the remove_if of the out-edges. garbage.push_back((*in_i.base()).get_iter()); } // Now remove the edges from this in-edge list. typename Config::in_edge_iterator first, last; tie(first, last) = in_edges(v, g); typedef typename Config::edge_parallel_category Cat; detail::remove_directed_edge_if_dispatch (first, last, in_edge_list(g, v), pred, Cat()); // Now delete the edge properties from the g.m_edges list for (typename Garbage::iterator i = garbage.begin(); i != garbage.end(); ++i) g.m_edges.erase(*i); } // O(1) template
inline typename Config::edges_size_type num_edges(const bidirectional_graph_helper_with_property
& g_) { typedef typename Config::graph_type graph_type; const graph_type& g = static_cast
(g_); return g.m_edges.size(); } // O(E/V * E/V) for allow_parallel_edge_tag // O(E/V * log(E/V)) for disallow_parallel_edge_tag template
inline void clear_vertex(typename Config::vertex_descriptor u, bidirectional_graph_helper_with_property
& g_) { typedef typename Config::global_edgelist_selector EdgeListS; BOOST_STATIC_ASSERT((!is_same
::value)); typedef typename Config::graph_type graph_type; typedef typename Config::edge_parallel_category Cat; graph_type& g = static_cast
(g_); typename Config::OutEdgeList& el = g.out_edge_list(u); typename Config::OutEdgeList::iterator ei = el.begin(), ei_end = el.end(); for (; ei != ei_end; ++ei) { detail::erase_from_incidence_list (in_edge_list(g, (*ei).get_target()), u, Cat()); g.m_edges.erase((*ei).get_iter()); } typename Config::InEdgeList& in_el = in_edge_list(g, u); typename Config::InEdgeList::iterator in_ei = in_el.begin(), in_ei_end = in_el.end(); for (; in_ei != in_ei_end; ++in_ei) { detail::erase_from_incidence_list (g.out_edge_list((*in_ei).get_target()), u, Cat()); g.m_edges.erase((*in_ei).get_iter()); } g.out_edge_list(u).clear(); in_edge_list(g, u).clear(); } template
inline void clear_out_edges(typename Config::vertex_descriptor u, bidirectional_graph_helper_with_property
& g_) { typedef typename Config::global_edgelist_selector EdgeListS; BOOST_STATIC_ASSERT((!is_same
::value)); typedef typename Config::graph_type graph_type; typedef typename Config::edge_parallel_category Cat; graph_type& g = static_cast
(g_); typename Config::OutEdgeList& el = g.out_edge_list(u); typename Config::OutEdgeList::iterator ei = el.begin(), ei_end = el.end(); for (; ei != ei_end; ++ei) { detail::erase_from_incidence_list (in_edge_list(g, (*ei).get_target()), u, Cat()); g.m_edges.erase((*ei).get_iter()); } g.out_edge_list(u).clear(); } template
inline void clear_in_edges(typename Config::vertex_descriptor u, bidirectional_graph_helper_with_property