klao@946: /* -*- C++ -*- klao@946: * src/lemon/graph_utils.h - Part of LEMON, a generic C++ optimization library klao@946: * alpar@1164: * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport alpar@1359: * (Egervary Research Group on Combinatorial Optimization, EGRES). klao@946: * klao@946: * Permission to use, modify and distribute this software is granted klao@946: * provided that this copyright notice appears in all copies. For klao@946: * precise terms see the accompanying LICENSE file. klao@946: * klao@946: * This software is provided "AS IS" with no warranty of any kind, klao@946: * express or implied, and with no claim as to its suitability for any klao@946: * purpose. klao@946: * klao@946: */ klao@946: klao@946: #ifndef LEMON_GRAPH_UTILS_H klao@946: #define LEMON_GRAPH_UTILS_H klao@946: klao@946: #include alpar@1402: #include klao@946: klao@946: #include klao@977: #include klao@946: alpar@947: ///\ingroup gutils klao@946: ///\file alpar@947: ///\brief Graph utilities. klao@946: /// alpar@964: ///\todo Please alpar@964: ///revise the documentation. alpar@964: /// klao@946: klao@946: klao@946: namespace lemon { klao@946: deba@1267: /// \addtogroup gutils deba@1267: /// @{ alpar@947: klao@946: /// \brief Function to count the items in the graph. klao@946: /// klao@946: /// This function counts the items in the graph. klao@946: /// The complexity of the function is O(n) because klao@946: /// it iterates on all of the items. klao@946: klao@946: template klao@977: inline int countItems(const Graph& g) { klao@946: int num = 0; klao@977: for (ItemIt it(g); it != INVALID; ++it) { klao@946: ++num; klao@946: } klao@946: return num; klao@946: } klao@946: klao@977: // Node counting: klao@977: klao@977: template klao@977: inline klao@977: typename enable_if::type klao@977: _countNodes(const Graph &g) { klao@977: return g.nodeNum(); klao@977: } klao@977: klao@977: template klao@977: inline int _countNodes(Wrap w) { klao@977: return countItems(w.value); klao@977: } klao@977: klao@946: /// \brief Function to count the nodes in the graph. klao@946: /// klao@946: /// This function counts the nodes in the graph. klao@946: /// The complexity of the function is O(n) but for some alpar@964: /// graph structure it is specialized to run in O(1). klao@977: /// klao@977: /// \todo refer how to specialize it klao@946: klao@946: template klao@977: inline int countNodes(const Graph& g) { klao@977: return _countNodes(g); klao@977: } klao@977: klao@977: // Edge counting: klao@977: klao@977: template klao@977: inline klao@977: typename enable_if::type klao@977: _countEdges(const Graph &g) { klao@977: return g.edgeNum(); klao@977: } klao@977: klao@977: template klao@977: inline int _countEdges(Wrap w) { klao@977: return countItems(w.value); klao@946: } klao@946: klao@946: /// \brief Function to count the edges in the graph. klao@946: /// klao@946: /// This function counts the edges in the graph. klao@946: /// The complexity of the function is O(e) but for some alpar@964: /// graph structure it is specialized to run in O(1). klao@977: klao@946: template klao@977: inline int countEdges(const Graph& g) { klao@977: return _countEdges(g); klao@946: } klao@946: klao@1053: // Undirected edge counting: klao@1053: klao@1053: template klao@1053: inline klao@1053: typename enable_if::type klao@1053: _countUndirEdges(const Graph &g) { klao@1053: return g.undirEdgeNum(); klao@1053: } klao@1053: klao@1053: template klao@1053: inline int _countUndirEdges(Wrap w) { klao@1053: return countItems(w.value); klao@1053: } klao@1053: klao@1053: /// \brief Function to count the edges in the graph. klao@946: /// klao@1053: /// This function counts the edges in the graph. klao@946: /// The complexity of the function is O(e) but for some alpar@964: /// graph structure it is specialized to run in O(1). klao@1053: klao@946: template klao@1053: inline int countUndirEdges(const Graph& g) { klao@1053: return _countUndirEdges(g); klao@946: } klao@946: klao@977: klao@1053: klao@946: template klao@946: inline int countNodeDegree(const Graph& _g, const typename Graph::Node& _n) { klao@946: int num = 0; klao@946: for (DegIt it(_g, _n); it != INVALID; ++it) { klao@946: ++num; klao@946: } klao@946: return num; klao@946: } alpar@967: alpar@967: /// Finds an edge between two nodes of a graph. alpar@967: alpar@967: /// Finds an edge from node \c u to node \c v in graph \c g. alpar@967: /// alpar@967: /// If \c prev is \ref INVALID (this is the default value), then alpar@967: /// it finds the first edge from \c u to \c v. Otherwise it looks for alpar@967: /// the next edge from \c u to \c v after \c prev. alpar@967: /// \return The found edge or \ref INVALID if there is no such an edge. alpar@967: /// alpar@967: /// Thus you can iterate through each edge from \c u to \c v as it follows. alpar@967: /// \code alpar@967: /// for(Edge e=findEdge(g,u,v);e!=INVALID;e=findEdge(g,u,v,e)) { alpar@967: /// ... alpar@967: /// } alpar@967: /// \endcode alpar@967: /// \todo We may want to use the \ref concept::GraphBase "GraphBase" alpar@967: /// interface here... alpar@967: /// \bug Untested ... alpar@967: template alpar@967: typename Graph::Edge findEdge(const Graph &g, deba@1267: typename Graph::Node u, typename Graph::Node v, deba@1267: typename Graph::Edge prev = INVALID) alpar@967: { alpar@967: typename Graph::OutEdgeIt e(g,prev); alpar@1079: // if(prev==INVALID) g.first(e,u); alpar@1079: if(prev==INVALID) e=typename Graph::OutEdgeIt(g,u); alpar@967: else ++e; alpar@1079: while(e!=INVALID && g.target(e)!=v) ++e; alpar@967: return e; alpar@967: } alpar@964: alpar@964: ///\e klao@946: alpar@964: ///\todo Please document. alpar@964: /// klao@946: template klao@946: inline int countOutEdges(const Graph& _g, const typename Graph::Node& _n) { klao@946: return countNodeDegree(_g, _n); klao@946: } klao@946: alpar@964: ///\e alpar@964: alpar@964: ///\todo Please document. alpar@964: /// klao@946: template klao@946: inline int countInEdges(const Graph& _g, const typename Graph::Node& _n) { klao@946: return countNodeDegree(_g, _n); klao@946: } klao@946: klao@946: // graph copy klao@946: klao@946: template < klao@946: typename DestinationGraph, klao@946: typename SourceGraph, klao@946: typename NodeBijection> klao@946: void copyNodes(DestinationGraph& _d, const SourceGraph& _s, klao@946: NodeBijection& _nb) { klao@946: for (typename SourceGraph::NodeIt it(_s); it != INVALID; ++it) { klao@946: _nb[it] = _d.addNode(); klao@946: } klao@946: } klao@946: klao@946: template < klao@946: typename DestinationGraph, klao@946: typename SourceGraph, klao@946: typename NodeBijection, klao@946: typename EdgeBijection> klao@946: void copyEdges(DestinationGraph& _d, const SourceGraph& _s, klao@946: const NodeBijection& _nb, EdgeBijection& _eb) { klao@946: for (typename SourceGraph::EdgeIt it(_s); it != INVALID; ++it) { alpar@986: _eb[it] = _d.addEdge(_nb[_s.source(it)], _nb[_s.target(it)]); klao@946: } klao@946: } klao@946: klao@946: template < klao@946: typename DestinationGraph, klao@946: typename SourceGraph, klao@946: typename NodeBijection, klao@946: typename EdgeBijection> klao@946: void copyGraph(DestinationGraph& _d, const SourceGraph& _s, klao@946: NodeBijection& _nb, EdgeBijection& _eb) { klao@946: nodeCopy(_d, _s, _nb); klao@946: edgeCopy(_d, _s, _nb, _eb); klao@946: } klao@946: deba@1267: template < klao@946: typename _DestinationGraph, klao@946: typename _SourceGraph, klao@946: typename _NodeBijection klao@946: =typename _SourceGraph::template NodeMap, klao@946: typename _EdgeBijection deba@1267: = typename _SourceGraph::template EdgeMap deba@1267: > deba@1267: class GraphCopy { deba@1267: public: deba@1267: deba@1267: typedef _DestinationGraph DestinationGraph; deba@1267: typedef _SourceGraph SourceGraph; klao@946: deba@1267: typedef _NodeBijection NodeBijection; deba@1267: typedef _EdgeBijection EdgeBijection; deba@1267: deba@1267: protected: deba@1267: deba@1267: NodeBijection node_bijection; deba@1267: EdgeBijection edge_bijection; klao@946: deba@1267: public: deba@1267: deba@1267: GraphCopy(DestinationGraph& _d, const SourceGraph& _s) { deba@1267: copyGraph(_d, _s, node_bijection, edge_bijection); deba@1267: } deba@1267: deba@1267: const NodeBijection& getNodeBijection() const { deba@1267: return node_bijection; deba@1267: } klao@946: deba@1267: const EdgeBijection& getEdgeBijection() const { deba@1267: return edge_bijection; deba@1267: } deba@1267: deba@1267: }; klao@946: klao@946: deba@1267: template deba@1267: class ItemSetTraits { deba@1267: }; deba@1192: deba@1192: template deba@1267: class ItemSetTraits<_Graph, typename _Graph::Node> { deba@1192: public: deba@1192: deba@1192: typedef _Graph Graph; alpar@947: deba@1192: typedef typename Graph::Node Item; deba@1192: typedef typename Graph::NodeIt ItemIt; deba@1192: deba@1192: template deba@1192: class Map : public Graph::template NodeMap<_Value> { deba@1192: public: deba@1192: typedef typename Graph::template NodeMap<_Value> Parent; deba@1192: typedef typename Parent::Value Value; deba@1192: deba@1192: Map(const Graph& _graph) : Parent(_graph) {} deba@1192: Map(const Graph& _graph, const Value& _value) deba@1192: : Parent(_graph, _value) {} deba@1192: }; deba@1192: deba@1192: }; deba@1192: deba@1192: template deba@1267: class ItemSetTraits<_Graph, typename _Graph::Edge> { deba@1192: public: deba@1192: deba@1192: typedef _Graph Graph; deba@1192: deba@1192: typedef typename Graph::Edge Item; deba@1192: typedef typename Graph::EdgeIt ItemIt; deba@1192: deba@1192: template deba@1192: class Map : public Graph::template EdgeMap<_Value> { deba@1192: public: deba@1192: typedef typename Graph::template EdgeMap<_Value> Parent; deba@1192: typedef typename Parent::Value Value; deba@1192: deba@1192: Map(const Graph& _graph) : Parent(_graph) {} deba@1192: Map(const Graph& _graph, const Value& _value) deba@1192: : Parent(_graph, _value) {} deba@1192: }; deba@1192: deba@1192: }; deba@1192: deba@1267: template deba@1267: class ItemSetTraits<_Graph, typename _Graph::UndirEdge> { deba@1267: public: deba@1267: deba@1267: typedef _Graph Graph; deba@1267: deba@1267: typedef typename Graph::UndirEdge Item; deba@1267: typedef typename Graph::UndirEdgeIt ItemIt; deba@1267: deba@1267: template deba@1267: class Map : public Graph::template UndirEdgeMap<_Value> { deba@1267: public: deba@1267: typedef typename Graph::template UndirEdgeMap<_Value> Parent; deba@1267: typedef typename Parent::Value Value; deba@1267: deba@1267: Map(const Graph& _graph) : Parent(_graph) {} deba@1267: Map(const Graph& _graph, const Value& _value) deba@1267: : Parent(_graph, _value) {} deba@1267: }; deba@1267: deba@1267: }; deba@1192: deba@1192: /// @} alpar@1402: alpar@1402: /// \addtogroup graph_maps alpar@1402: /// @{ alpar@1402: alpar@1402: /// Provides an immutable and unique id for each item in the graph. alpar@1402: alpar@1402: /// The IdMap class provides an unique and immutable mapping for each item alpar@1402: /// in the graph. alpar@1402: /// alpar@1402: template alpar@1402: class IdMap { alpar@1402: public: alpar@1402: typedef _Graph Graph; alpar@1402: typedef int Value; alpar@1402: typedef _Item Item; alpar@1402: typedef _Item Key; alpar@1402: alpar@1402: /// \brief The class represents the inverse of the map. alpar@1402: /// alpar@1402: /// The class represents the inverse of the map. alpar@1402: /// \see inverse() alpar@1402: class InverseMap { alpar@1402: public: alpar@1402: /// \brief Constructor. alpar@1402: /// alpar@1402: /// Constructor for creating an id-to-item map. alpar@1402: InverseMap(const Graph& _graph) : graph(&_graph) {} alpar@1402: /// \brief Gives back the given item from its id. alpar@1402: /// alpar@1402: /// Gives back the given item from its id. alpar@1402: /// alpar@1402: Item operator[](int id) const { return graph->fromId(id, Item());} alpar@1402: private: alpar@1402: const Graph* graph; alpar@1402: }; alpar@1402: alpar@1402: /// \brief Constructor. alpar@1402: /// alpar@1402: /// Constructor for creating id map. alpar@1402: IdMap(const Graph& _graph) : graph(&_graph) {} alpar@1402: alpar@1402: /// \brief Gives back the \e id of the item. alpar@1402: /// alpar@1402: /// Gives back the immutable and unique \e id of the map. alpar@1402: int operator[](const Item& item) const { return graph->id(item);} alpar@1402: alpar@1402: /// \brief Gives back the inverse of the map. alpar@1402: /// alpar@1402: /// Gives back the inverse of the map. alpar@1402: InverseMap inverse() const { return InverseMap(*graph);} alpar@1402: alpar@1402: private: alpar@1402: const Graph* graph; alpar@1402: alpar@1402: }; alpar@1402: alpar@947: alpar@1402: template alpar@1402: struct ReferenceMapTraits { alpar@1402: typedef typename Map::Value Value; alpar@1402: typedef typename Map::Value& Reference; alpar@1402: typedef const typename Map::Value& ConstReference; alpar@1402: typedef typename Map::Value* Pointer; alpar@1402: typedef const typename Map::Value* ConstPointer; alpar@1402: }; alpar@1402: alpar@1402: template alpar@1402: struct ReferenceMapTraits< alpar@1402: Map, alpar@1402: typename enable_if::type alpar@1402: > { alpar@1402: typedef typename Map::Value Value; alpar@1402: typedef typename Map::Reference Reference; alpar@1402: typedef typename Map::ConstReference ConstReference; alpar@1402: typedef typename Map::Pointer Pointer; alpar@1402: typedef typename Map::ConstPointer ConstPointer; alpar@1402: }; alpar@1402: alpar@1402: /// \brief General inversable graph-map type. alpar@1402: alpar@1402: /// This type provides simple inversable map functions. alpar@1402: /// The InversableMap wraps an arbitrary ReadWriteMap alpar@1402: /// and if a key is setted to a new value then store it alpar@1402: /// in the inverse map. alpar@1402: /// \param _Graph The graph type. alpar@1402: /// \param _Map The map to extend with inversable functionality. alpar@1402: template < alpar@1402: typename _Graph, alpar@1402: typename _Item, alpar@1402: typename _Value, alpar@1402: typename _Map alpar@1402: = typename ItemSetTraits<_Graph, _Item>::template Map<_Value> alpar@1402: > alpar@1402: class InversableMap : protected _Map { alpar@1402: alpar@1402: public: alpar@1402: alpar@1402: typedef _Map Map; alpar@1402: typedef _Graph Graph; alpar@1402: /// The key type of InversableMap (Node, Edge, UndirEdge). alpar@1402: typedef typename _Map::Key Key; alpar@1402: /// The value type of the InversableMap. alpar@1402: typedef typename _Map::Value Value; alpar@1402: alpar@1402: typedef std::map InverseMap; alpar@1402: alpar@1402: typedef typename _Map::ConstReference ConstReference; alpar@1402: alpar@1402: /// \brief Constructor. alpar@1402: /// alpar@1402: /// Construct a new InversableMap for the graph. alpar@1402: /// alpar@1402: InversableMap(const Graph& graph) : Map(graph) {} alpar@1402: alpar@1402: /// \brief The setter function of the map. alpar@1402: /// alpar@1402: alpar@1402: void set(const Key& key, const Value& val) { alpar@1402: Value oldval = Map::operator[](key); alpar@1402: typename InverseMap::iterator it = invMap.find(oldval); alpar@1402: if (it != invMap.end() && it->second == key) { alpar@1402: invMap.erase(it); alpar@1402: } alpar@1402: invMap.insert(make_pair(val, key)); alpar@1402: Map::set(key, val); alpar@1402: } alpar@1402: alpar@1402: /// \brief The getter function of the map. alpar@1402: /// alpar@1402: /// It gives back the value associated with the key. alpar@1402: ConstReference operator[](const Key& key) const { alpar@1402: return Map::operator[](key); alpar@1402: } alpar@1402: alpar@1402: /// \brief Add a new key to the map. alpar@1402: /// alpar@1402: /// Add a new key to the map. It is called by the alpar@1402: /// \c AlterationNotifier. alpar@1402: virtual void add(const Key& key) { alpar@1402: Map::add(key); alpar@1402: } alpar@1402: alpar@1402: /// \brief Erase the key from the map. alpar@1402: /// alpar@1402: /// Erase the key to the map. It is called by the alpar@1402: /// \c AlterationNotifier. alpar@1402: virtual void erase(const Key& key) { alpar@1402: Value val = Map::operator[](key); alpar@1402: typename InverseMap::iterator it = invMap.find(val); alpar@1402: if (it != invMap.end() && it->second == key) { alpar@1402: invMap.erase(it); alpar@1402: } alpar@1402: Map::erase(key); alpar@1402: } alpar@1402: alpar@1402: /// \brief Clear the keys from the map and inverse map. alpar@1402: /// alpar@1402: /// Clear the keys from the map and inverse map. It is called by the alpar@1402: /// \c AlterationNotifier. alpar@1402: virtual void clear() { alpar@1402: invMap.clear(); alpar@1402: Map::clear(); alpar@1402: } alpar@1402: alpar@1402: /// \brief It gives back the just readeable inverse map. alpar@1402: /// alpar@1402: /// It gives back the just readeable inverse map. alpar@1402: const InverseMap& inverse() const { alpar@1402: return invMap; alpar@1402: } alpar@1402: alpar@1402: alpar@1402: private: alpar@1402: InverseMap invMap; alpar@1402: }; alpar@1402: alpar@1402: /// \brief Provides a mutable, continuous and unique descriptor for each alpar@1402: /// item in the graph. alpar@1402: /// alpar@1402: /// The DescriptorMap class provides a mutable, continuous and immutable alpar@1402: /// mapping for each item in the graph. alpar@1402: /// alpar@1402: /// \param _Graph The graph class the \c DescriptorMap belongs to. alpar@1402: /// \param _Item The Item is the Key of the Map. It may be Node, Edge or alpar@1402: /// UndirEdge. alpar@1402: /// \param _Map A ReadWriteMap mapping from the item type to integer. alpar@1402: alpar@1402: template < alpar@1402: typename _Graph, alpar@1402: typename _Item, alpar@1402: typename _Map = typename ItemSetTraits<_Graph, _Item>::template Map alpar@1402: > alpar@1402: class DescriptorMap : protected _Map { alpar@1402: alpar@1402: typedef _Item Item; alpar@1402: typedef _Map Map; alpar@1402: alpar@1402: public: alpar@1402: /// The graph class of DescriptorMap. alpar@1402: typedef _Graph Graph; alpar@1402: alpar@1402: /// The key type of DescriptorMap (Node, Edge, UndirEdge). alpar@1402: typedef typename _Map::Key Key; alpar@1402: /// The value type of DescriptorMap. alpar@1402: typedef typename _Map::Value Value; alpar@1402: alpar@1402: typedef std::vector InverseMap; alpar@1402: alpar@1402: /// \brief Constructor. alpar@1402: /// alpar@1402: /// Constructor for creating descriptor map. alpar@1402: DescriptorMap(const Graph& _graph) : Map(_graph) { alpar@1402: build(); alpar@1402: } alpar@1402: alpar@1402: /// \brief Add a new key to the map. alpar@1402: /// alpar@1402: /// Add a new key to the map. It is called by the alpar@1402: /// \c AlterationNotifier. alpar@1402: virtual void add(const Item& item) { alpar@1402: Map::add(item); alpar@1402: Map::set(item, invMap.size()); alpar@1402: invMap.push_back(item); alpar@1402: } alpar@1402: alpar@1402: /// \brief Erase the key from the map. alpar@1402: /// alpar@1402: /// Erase the key to the map. It is called by the alpar@1402: /// \c AlterationNotifier. alpar@1402: virtual void erase(const Item& item) { alpar@1402: Map::set(invMap.back(), Map::operator[](item)); alpar@1402: invMap[Map::operator[](item)] = invMap.back(); alpar@1402: Map::erase(item); alpar@1402: } alpar@1402: alpar@1402: /// \brief Build the unique map. alpar@1402: /// alpar@1402: /// Build the unique map. It is called by the alpar@1402: /// \c AlterationNotifier. alpar@1402: virtual void build() { alpar@1402: Map::build(); alpar@1402: Item it; alpar@1402: const typename Map::Graph* graph = Map::getGraph(); alpar@1402: for (graph->first(it); it != INVALID; graph->next(it)) { alpar@1402: Map::set(it, invMap.size()); alpar@1402: invMap.push_back(it); alpar@1402: } alpar@1402: } alpar@1402: alpar@1402: /// \brief Clear the keys from the map. alpar@1402: /// alpar@1402: /// Clear the keys from the map. It is called by the alpar@1402: /// \c AlterationNotifier. alpar@1402: virtual void clear() { alpar@1402: invMap.clear(); alpar@1402: Map::clear(); alpar@1402: } alpar@1402: alpar@1402: /// \brief Gives back the \e descriptor of the item. alpar@1402: /// alpar@1402: /// Gives back the mutable and unique \e descriptor of the map. alpar@1402: int operator[](const Item& item) const { alpar@1402: return Map::operator[](item); alpar@1402: } alpar@1402: alpar@1402: /// \brief Gives back the inverse of the map. alpar@1402: /// alpar@1402: /// Gives back the inverse of the map. alpar@1402: const InverseMap inverse() const { alpar@1402: return invMap; alpar@1402: } alpar@1402: alpar@1402: private: alpar@1402: std::vector invMap; alpar@1402: }; alpar@1402: alpar@1402: /// \brief Returns the source of the given edge. alpar@1402: /// alpar@1402: /// The SourceMap gives back the source Node of the given edge. alpar@1402: /// \author Balazs Dezso alpar@1402: template alpar@1402: class SourceMap { alpar@1402: public: alpar@1402: typedef typename Graph::Node Value; alpar@1402: typedef typename Graph::Edge Key; alpar@1402: alpar@1402: /// \brief Constructor alpar@1402: /// alpar@1402: /// Constructor alpar@1402: /// \param _graph The graph that the map belongs to. alpar@1402: SourceMap(const Graph& _graph) : graph(_graph) {} alpar@1402: alpar@1402: /// \brief The subscript operator. alpar@1402: /// alpar@1402: /// The subscript operator. alpar@1402: /// \param edge The edge alpar@1402: /// \return The source of the edge alpar@1402: Value operator[](const Key& edge) { alpar@1402: return graph.source(edge); alpar@1402: } alpar@1402: alpar@1402: private: alpar@1402: const Graph& graph; alpar@1402: }; alpar@1402: alpar@1402: /// \brief Returns a \ref SourceMap class alpar@1402: /// alpar@1402: /// This function just returns an \ref SourceMap class. alpar@1402: /// \relates SourceMap alpar@1402: template alpar@1402: inline SourceMap sourceMap(const Graph& graph) { alpar@1402: return SourceMap(graph); alpar@1402: } alpar@1402: alpar@1402: /// \brief Returns the target of the given edge. alpar@1402: /// alpar@1402: /// The TargetMap gives back the target Node of the given edge. alpar@1402: /// \author Balazs Dezso alpar@1402: template alpar@1402: class TargetMap { alpar@1402: public: alpar@1402: typedef typename Graph::Node Value; alpar@1402: typedef typename Graph::Edge Key; alpar@1402: alpar@1402: /// \brief Constructor alpar@1402: /// alpar@1402: /// Constructor alpar@1402: /// \param _graph The graph that the map belongs to. alpar@1402: TargetMap(const Graph& _graph) : graph(_graph) {} alpar@1402: alpar@1402: /// \brief The subscript operator. alpar@1402: /// alpar@1402: /// The subscript operator. alpar@1402: /// \param edge The edge alpar@1402: /// \return The target of the edge alpar@1402: Value operator[](const Key& key) { alpar@1402: return graph.target(key); alpar@1402: } alpar@1402: alpar@1402: private: alpar@1402: const Graph& graph; alpar@1402: }; alpar@1402: alpar@1402: /// \brief Returns a \ref TargetMap class alpar@1402: alpar@1402: /// This function just returns an \ref TargetMap class. alpar@1402: /// \relates TargetMap alpar@1402: template alpar@1402: inline TargetMap targetMap(const Graph& graph) { alpar@1402: return TargetMap(graph); alpar@1402: } alpar@1402: alpar@1402: alpar@1402: /// @} alpar@1402: alpar@947: } //END OF NAMESPACE LEMON klao@946: klao@946: #endif