lemon/path.h
author deba
Tue, 11 Dec 2007 17:42:49 +0000
changeset 2540 8ab1d3d7dea7
parent 2419 6a567c0f1214
child 2553 bfced05fa852
permissions -rw-r--r--
Avoiding warnings
     1 /* -*- C++ -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library
     4  *
     5  * Copyright (C) 2003-2007
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     9  * Permission to use, modify and distribute this software is granted
    10  * provided that this copyright notice appears in all copies. For
    11  * precise terms see the accompanying LICENSE file.
    12  *
    13  * This software is provided "AS IS" with no warranty of any kind,
    14  * express or implied, and with no claim as to its suitability for any
    15  * purpose.
    16  *
    17  */
    18 
    19 ///\ingroup paths
    20 ///\file
    21 ///\brief Classes for representing paths in graphs.
    22 ///
    23 
    24 #ifndef LEMON_PATH_H
    25 #define LEMON_PATH_H
    26 
    27 #include <vector>
    28 #include <algorithm>
    29 
    30 #include <lemon/path_utils.h>
    31 #include <lemon/error.h>
    32 #include <lemon/bits/invalid.h>
    33 
    34 namespace lemon {
    35 
    36   /// \addtogroup paths
    37   /// @{
    38 
    39 
    40   /// \brief A structure for representing directed paths in a graph.
    41   ///
    42   /// A structure for representing directed path in a graph.
    43   /// \param Graph The graph type in which the path is.
    44   ///
    45   /// In a sense, the path can be treated as a list of edges. The
    46   /// lemon path type stores just this list. As a consequence it
    47   /// cannot enumerate the nodes in the path and the zero length paths
    48   /// cannot store the source.
    49   ///
    50   /// This implementation is a back and front insertable and erasable
    51   /// path type. It can be indexed in O(1) time. The front and back
    52   /// insertion and erasure is amortized O(1) time. The
    53   /// impelementation is based on two opposite organized vectors.
    54   template <typename _Graph>
    55   class Path {
    56   public:
    57 
    58     typedef _Graph Graph;
    59     typedef typename Graph::Edge Edge;
    60 
    61     /// \brief Default constructor
    62     ///
    63     /// Default constructor
    64     Path() {}
    65 
    66     /// \brief Template copy constructor
    67     ///
    68     /// This path can be initialized with any other path type. It just
    69     /// makes a copy of the given path.
    70     template <typename CPath>
    71     Path(const CPath& cpath) {
    72       copyPath(*this, cpath);
    73     }
    74 
    75     /// \brief Template copy assignment
    76     ///
    77     /// This path can be initialized with any other path type. It just
    78     /// makes a copy of the given path.
    79     template <typename CPath>
    80     Path& operator=(const CPath& cpath) {
    81       copyPath(*this, cpath);
    82       return *this;
    83     }
    84 
    85     /// \brief Lemon style iterator for path edges
    86     ///
    87     /// This class is used to iterate on the edges of the paths.
    88     class EdgeIt {
    89       friend class Path;
    90     public:
    91       /// \brief Default constructor
    92       EdgeIt() {}
    93       /// \brief Invalid constructor
    94       EdgeIt(Invalid) : path(0), idx(-1) {}
    95       /// \brief Initializate the constructor to the first edge of path
    96       EdgeIt(const Path &_path) 
    97         : path(&_path), idx(_path.empty() ? -1 : 0) {}
    98 
    99     private:
   100 
   101       EdgeIt(const Path &_path, int _idx) 
   102         : path(&_path), idx(_idx) {}
   103 
   104     public:
   105 
   106       /// \brief Conversion to Edge
   107       operator const Edge&() const {
   108         return path->nth(idx);
   109       }
   110 
   111       /// \brief Next edge
   112       EdgeIt& operator++() { 
   113         ++idx;
   114         if (idx >= path->length()) idx = -1; 
   115         return *this; 
   116       }
   117 
   118       /// \brief Comparison operator
   119       bool operator==(const EdgeIt& e) const { return idx==e.idx; }
   120       /// \brief Comparison operator
   121       bool operator!=(const EdgeIt& e) const { return idx!=e.idx; }
   122       /// \brief Comparison operator
   123       bool operator<(const EdgeIt& e) const { return idx<e.idx; }
   124 
   125     private:
   126       const Path *path;
   127       int idx;
   128     };
   129 
   130     /// \brief Length of the path.
   131     int length() const { return head.size() + tail.size(); }
   132     /// \brief Returns whether the path is empty.
   133     bool empty() const { return head.empty() && tail.empty(); }
   134 
   135     /// \brief Resets the path to an empty path.
   136     void clear() { head.clear(); tail.clear(); }
   137 
   138     /// \brief Gives back the nth edge.
   139     ///
   140     /// \pre n is in the [0..length() - 1] range
   141     const Edge& nth(int n) const {
   142       return n < int(head.size()) ? *(head.rbegin() + n) :
   143         *(tail.begin() + (n - head.size()));
   144     }
   145 
   146     /// \brief Initializes edge iterator to point to the nth edge
   147     ///
   148     /// \pre n is in the [0..length() - 1] range
   149     EdgeIt nthIt(int n) const {
   150       return EdgeIt(*this, n);
   151     }
   152 
   153     /// \brief Gives back the first edge of the path
   154     const Edge& front() const {
   155       return head.empty() ? tail.front() : head.back();
   156     }
   157 
   158     /// \brief Add a new edge before the current path
   159     void addFront(const Edge& edge) {
   160       head.push_back(edge);
   161     }
   162 
   163     /// \brief Erase the first edge of the path
   164     void eraseFront() {
   165       if (!head.empty()) {
   166         head.pop_back();
   167       } else {
   168         head.clear();
   169         int halfsize = tail.size() / 2;
   170         head.resize(halfsize);
   171         std::copy(tail.begin() + 1, tail.begin() + halfsize + 1,
   172                   head.rbegin());
   173         std::copy(tail.begin() + halfsize + 1, tail.end(), tail.begin());
   174         tail.resize(tail.size() - halfsize - 1);
   175       }
   176     }
   177 
   178     /// \brief Gives back the last edge of the path
   179     const Edge& back() const {
   180       return tail.empty() ? head.front() : tail.back();
   181     }
   182 
   183     /// \brief Add a new edge behind the current path
   184     void addBack(const Edge& edge) {
   185       tail.push_back(edge);
   186     }
   187 
   188     /// \brief Erase the last edge of the path
   189     void eraseBack() {
   190       if (!tail.empty()) {
   191         tail.pop_back();
   192       } else {
   193         int halfsize = head.size() / 2;
   194         tail.resize(halfsize);
   195         std::copy(head.begin() + 1, head.begin() + halfsize + 1,
   196                   tail.rbegin());
   197         std::copy(head.begin() + halfsize + 1, head.end(), head.begin());
   198         head.resize(head.size() - halfsize - 1);
   199       }
   200     }
   201 
   202 
   203 
   204     typedef True BuildTag;
   205 
   206     template <typename CPath>
   207     void build(const CPath& path) {
   208       int len = path.length();
   209       tail.reserve(len);
   210       for (typename CPath::EdgeIt it(path); it != INVALID; ++it) {
   211         tail.push_back(it);
   212       }
   213     }
   214 
   215     template <typename CPath>
   216     void buildRev(const CPath& path) {
   217       int len = path.length();
   218       head.reserve(len);
   219       for (typename CPath::RevEdgeIt it(path); it != INVALID; ++it) {
   220         head.push_back(it);
   221       }
   222     }
   223 
   224   protected:
   225     typedef std::vector<Edge> Container;
   226     Container head, tail;
   227 
   228   };
   229 
   230   /// \brief A structure for representing directed paths in a graph.
   231   ///
   232   /// A structure for representing directed path in a graph.
   233   /// \param Graph The graph type in which the path is.
   234   ///
   235   /// In a sense, the path can be treated as a list of edges. The
   236   /// lemon path type stores just this list. As a consequence it
   237   /// cannot enumerate the nodes in the path and the zero length paths
   238   /// cannot store the source.
   239   ///
   240   /// This implementation is a just back insertable and erasable path
   241   /// type. It can be indexed in O(1) time. The back insertion and
   242   /// erasure is amortized O(1) time. This implementation is faster
   243   /// then the \c Path type because it use just one vector for the
   244   /// edges.
   245   template <typename _Graph>
   246   class SimplePath {
   247   public:
   248 
   249     typedef _Graph Graph;
   250     typedef typename Graph::Edge Edge;
   251 
   252     /// \brief Default constructor
   253     ///
   254     /// Default constructor
   255     SimplePath() {}
   256 
   257     /// \brief Template copy constructor
   258     ///
   259     /// This path can be initialized with any other path type. It just
   260     /// makes a copy of the given path.
   261     template <typename CPath>
   262     SimplePath(const CPath& cpath) {
   263       copyPath(*this, cpath);
   264     }
   265 
   266     /// \brief Template copy assignment
   267     ///
   268     /// This path can be initialized with any other path type. It just
   269     /// makes a copy of the given path.
   270     template <typename CPath>
   271     SimplePath& operator=(const CPath& cpath) {
   272       copyPath(*this, cpath);
   273       return *this;
   274     }
   275 
   276     /// \brief Iterator class to iterate on the edges of the paths
   277     ///
   278     /// This class is used to iterate on the edges of the paths
   279     ///
   280     /// Of course it converts to Graph::Edge
   281     class EdgeIt {
   282       friend class SimplePath;
   283     public:
   284       /// Default constructor
   285       EdgeIt() {}
   286       /// Invalid constructor
   287       EdgeIt(Invalid) : path(0), idx(-1) {}
   288       /// \brief Initializate the constructor to the first edge of path
   289       EdgeIt(const SimplePath &_path) 
   290         : path(&_path), idx(_path.empty() ? -1 : 0) {}
   291 
   292     private:
   293 
   294       /// Constructor with starting point
   295       EdgeIt(const SimplePath &_path, int _idx) 
   296         : idx(_idx), path(&_path) {}
   297 
   298     public:
   299 
   300       ///Conversion to Graph::Edge
   301       operator const Edge&() const {
   302         return path->nth(idx);
   303       }
   304 
   305       /// Next edge
   306       EdgeIt& operator++() { 
   307         ++idx;
   308         if (idx >= path->length()) idx = -1; 
   309         return *this; 
   310       }
   311 
   312       /// Comparison operator
   313       bool operator==(const EdgeIt& e) const { return idx==e.idx; }
   314       /// Comparison operator
   315       bool operator!=(const EdgeIt& e) const { return idx!=e.idx; }
   316       /// Comparison operator
   317       bool operator<(const EdgeIt& e) const { return idx<e.idx; }
   318 
   319     private:
   320       const SimplePath *path;
   321       int idx;
   322     };
   323 
   324     /// \brief Length of the path.
   325     int length() const { return data.size(); }
   326     /// \brief Returns whether the path is empty.
   327     bool empty() const { return data.empty(); }
   328 
   329     /// \brief Resets the path to an empty path.
   330     void clear() { data.clear(); }
   331 
   332     /// \brief Gives back the nth edge.
   333     ///
   334     /// \pre n is in the [0..length() - 1] range
   335     const Edge& nth(int n) const {
   336       return data[n];
   337     }
   338 
   339     /// \brief  Initializes edge iterator to point to the nth edge.
   340     EdgeIt nthIt(int n) const {
   341       return EdgeIt(*this, n);
   342     }
   343 
   344     /// \brief Gives back the first edge of the path.
   345     const Edge& front() const {
   346       return data.front();
   347     }
   348 
   349     /// \brief Gives back the last edge of the path.
   350     const Edge& back() const {
   351       return data.back();
   352     }
   353 
   354     /// \brief Add a new edge behind the current path.
   355     void addBack(const Edge& edge) {
   356       data.push_back(edge);
   357     }
   358 
   359     /// \brief Erase the last edge of the path
   360     void eraseBack() {
   361       data.pop_back();
   362     }
   363 
   364     typedef True BuildTag;
   365 
   366     template <typename CPath>
   367     void build(const CPath& path) {
   368       int len = path.length();
   369       data.resize(len);
   370       int index = 0;
   371       for (typename CPath::EdgeIt it(path); it != INVALID; ++it) {
   372         data[index] = it;;
   373         ++index;
   374       }
   375     }
   376 
   377     template <typename CPath>
   378     void buildRev(const CPath& path) {
   379       int len = path.length();
   380       data.resize(len);
   381       int index = len;
   382       for (typename CPath::RevEdgeIt it(path); it != INVALID; ++it) {
   383         --index;
   384         data[index] = it;;
   385       }
   386     }
   387 
   388   protected:
   389     typedef std::vector<Edge> Container;
   390     Container data;
   391 
   392   };
   393 
   394   /// \brief A structure for representing directed paths in a graph.
   395   ///
   396   /// A structure for representing directed path in a graph.
   397   /// \param Graph The graph type in which the path is.
   398   ///
   399   /// In a sense, the path can be treated as a list of edges. The
   400   /// lemon path type stores just this list. As a consequence it
   401   /// cannot enumerate the nodes in the path and the zero length paths
   402   /// cannot store the source.
   403   ///
   404   /// This implementation is a back and front insertable and erasable
   405   /// path type. It can be indexed in O(k) time, where k is the rank
   406   /// of the edge in the path. The length can be computed in O(n)
   407   /// time. The front and back insertion and erasure is O(1) time
   408   /// and it can be splited and spliced in O(1) time.
   409   template <typename _Graph>
   410   class ListPath {
   411   public:
   412 
   413     typedef _Graph Graph;
   414     typedef typename Graph::Edge Edge;
   415 
   416   protected:
   417 
   418     // the std::list<> is incompatible 
   419     // hard to create invalid iterator
   420     struct Node {
   421       Edge edge;
   422       Node *next, *prev;
   423     };
   424 
   425     Node *first, *last;
   426 
   427     std::allocator<Node> alloc;
   428 
   429   public:
   430  
   431     /// \brief Default constructor
   432     ///
   433     /// Default constructor
   434     ListPath() : first(0), last(0) {}
   435 
   436     /// \brief Template copy constructor
   437     ///
   438     /// This path can be initialized with any other path type. It just
   439     /// makes a copy of the given path.
   440     template <typename CPath>
   441     ListPath(const CPath& cpath) : first(0), last(0) {
   442       copyPath(*this, cpath);
   443     }
   444 
   445     /// \brief Destructor of the path
   446     ///
   447     /// Destructor of the path
   448     ~ListPath() {
   449       clear();
   450     }
   451 
   452     /// \brief Template copy assignment
   453     ///
   454     /// This path can be initialized with any other path type. It just
   455     /// makes a copy of the given path.
   456     template <typename CPath>
   457     ListPath& operator=(const CPath& cpath) {
   458       copyPath(*this, cpath);
   459       return *this;
   460     }
   461 
   462     /// \brief Iterator class to iterate on the edges of the paths
   463     ///
   464     /// This class is used to iterate on the edges of the paths
   465     ///
   466     /// Of course it converts to Graph::Edge
   467     class EdgeIt {
   468       friend class ListPath;
   469     public:
   470       /// Default constructor
   471       EdgeIt() {}
   472       /// Invalid constructor
   473       EdgeIt(Invalid) : path(0), node(0) {}
   474       /// \brief Initializate the constructor to the first edge of path
   475       EdgeIt(const ListPath &_path) 
   476         : path(&_path), node(_path.first) {}
   477 
   478     protected:
   479 
   480       EdgeIt(const ListPath &_path, Node *_node) 
   481         : path(&_path), node(_node) {}
   482 
   483 
   484     public:
   485 
   486       ///Conversion to Graph::Edge
   487       operator const Edge&() const {
   488         return node->edge;
   489       }
   490 
   491       /// Next edge
   492       EdgeIt& operator++() { 
   493         node = node->next;
   494         return *this; 
   495       }
   496 
   497       /// Comparison operator
   498       bool operator==(const EdgeIt& e) const { return node==e.node; }
   499       /// Comparison operator
   500       bool operator!=(const EdgeIt& e) const { return node!=e.node; }
   501       /// Comparison operator
   502       bool operator<(const EdgeIt& e) const { return node<e.node; }
   503 
   504     private:
   505       const ListPath *path;
   506       Node *node;
   507     };
   508 
   509     /// \brief Gives back the nth edge.
   510     ///
   511     /// Gives back the nth edge in O(n) time.
   512     /// \pre n is in the [0..length() - 1] range
   513     const Edge& nth(int n) const {
   514       Node *node = first;
   515       for (int i = 0; i < n; ++i) {
   516         node = node->next;
   517       }
   518       return node->edge;
   519     }
   520 
   521     /// \brief Initializes edge iterator to point to the nth edge.
   522     EdgeIt nthIt(int n) const {
   523       Node *node = first;
   524       for (int i = 0; i < n; ++i) {
   525         node = node->next;
   526       }
   527       return EdgeIt(*this, node);
   528     }
   529 
   530     /// \brief Length of the path.
   531     int length() const {
   532       int len = 0;
   533       Node *node = first;
   534       while (node != 0) {
   535         node = node->next;
   536         ++len;
   537       }
   538       return len;
   539     }
   540 
   541     /// \brief Returns whether the path is empty.
   542     bool empty() const { return first == 0; }
   543 
   544     /// \brief Resets the path to an empty path.
   545     void clear() {
   546       while (first != 0) {
   547         last = first->next;
   548         alloc.destroy(first);
   549         alloc.deallocate(first, 1);
   550         first = last;
   551       }
   552     }
   553 
   554     /// \brief Gives back the first edge of the path
   555     const Edge& front() const {
   556       return first->edge;
   557     }
   558 
   559     /// \brief Add a new edge before the current path
   560     void addFront(const Edge& edge) {
   561       Node *node = alloc.allocate(1);
   562       alloc.construct(node, Node());
   563       node->prev = 0;
   564       node->next = first;
   565       node->edge = edge;
   566       if (first) {
   567         first->prev = node;
   568         first = node;
   569       } else {
   570         first = last = node;
   571       }
   572     }
   573 
   574     /// \brief Erase the first edge of the path
   575     void eraseFront() {
   576       Node *node = first;
   577       first = first->next;
   578       if (first) {
   579         first->prev = 0;
   580       } else {
   581         last = 0;
   582       }
   583       alloc.destroy(node);
   584       alloc.deallocate(node, 1);
   585     }
   586 
   587     /// \brief Gives back the last edge of the path.
   588     const Edge& back() const {
   589       return last->edge;
   590     }
   591 
   592     /// \brief Add a new edge behind the current path.
   593     void addBack(const Edge& edge) {
   594       Node *node = alloc.allocate(1);
   595       alloc.construct(node, Node());
   596       node->next = 0;
   597       node->prev = last;
   598       node->edge = edge;
   599       if (last) {
   600         last->next = node;
   601         last = node;
   602       } else {
   603         last = first = node;
   604       }
   605     }
   606 
   607     /// \brief Erase the last edge of the path
   608     void eraseBack() {
   609       Node *node = last;
   610       last = last->prev;
   611       if (last) {
   612         last->next = 0;
   613       } else {
   614         first = 0;
   615       }
   616       alloc.destroy(node);
   617       alloc.deallocate(node, 1);
   618     }
   619 
   620     /// \brief Splicing the given path to the current path.
   621     ///
   622     /// It splices the \c tpath to the back of the current path and \c
   623     /// tpath becomes empty. The time complexity of this function is
   624     /// O(1).
   625     void spliceBack(ListPath& tpath) {
   626       if (first) {
   627         if (tpath.first) {
   628           last->next = tpath.first;
   629           tpath.first->prev = last;
   630           last = tpath.last;
   631         }
   632       } else {
   633         first = tpath.first;
   634         last = tpath.last;
   635       }
   636       tpath.first = tpath.last = 0;
   637     }
   638 
   639     /// \brief Splicing the given path to the current path.
   640     ///
   641     /// It splices the \c tpath before the current path and \c tpath
   642     /// becomes empty. The time complexity of this function
   643     /// is O(1).
   644     void spliceFront(ListPath& tpath) {
   645       if (first) {
   646         if (tpath.first) {
   647           first->prev = tpath.last;
   648           tpath.last->next = first;
   649           first = tpath.first;
   650         }
   651       } else {
   652         first = tpath.first;
   653         last = tpath.last;
   654       }
   655       tpath.first = tpath.last = 0;
   656     }
   657 
   658     /// \brief Splicing the given path into the current path.
   659     ///
   660     /// It splices the \c tpath into the current path before the
   661     /// position of \c it iterator and \c tpath becomes empty. The
   662     /// time complexity of this function is O(1). If the \c it is \c
   663     /// INVALID then it will splice behind the current path.
   664     void splice(EdgeIt it, ListPath& tpath) {
   665       if (it.node) {
   666         if (tpath.first) {
   667           tpath.first->prev = it.node->prev;
   668           if (it.node->prev) {
   669             it.node->prev->next = tpath.first;
   670           } else {
   671             first = tpath.first;
   672           }
   673           it.node->prev = tpath.last;
   674           tpath.last->next = it.node;
   675         }
   676       } else {
   677         if (first) {
   678           if (tpath.first) {
   679             last->next = tpath.first;
   680             tpath.first->prev = last;
   681             last = tpath.last;
   682           }
   683         } else {
   684           first = tpath.first;
   685           last = tpath.last;
   686         }
   687       }
   688       tpath.first = tpath.last = 0;
   689     }
   690 
   691     /// \brief Spliting the current path.
   692     ///
   693     /// It splits the current path into two parts. The part before \c
   694     /// it iterator will remain in the current path and the part from
   695     /// the it will put into the \c tpath. If the \c tpath had edges
   696     /// before the operation they will be removed first.  The time
   697     /// complexity of this function is O(1) plus the clearing of \c
   698     /// tpath. If the \c it is \c INVALID then it just clears \c
   699     /// tpath.
   700     void split(EdgeIt it, ListPath& tpath) {
   701       tpath.clear();
   702       if (it.node) {
   703         tpath.first = it.node;
   704         tpath.last = last;
   705         if (it.node->prev) {
   706           last = it.node->prev;
   707           last->next = 0;
   708         } else {
   709           first = last = 0;
   710         }
   711         it.node->prev = 0;
   712       }
   713     }
   714 
   715 
   716     typedef True BuildTag;
   717 
   718     template <typename CPath>
   719     void build(const CPath& path) {
   720       for (typename CPath::EdgeIt it(path); it != INVALID; ++it) {
   721         addBack(it);
   722       }
   723     }
   724 
   725     template <typename CPath>
   726     void buildRev(const CPath& path) {
   727       for (typename CPath::RevEdgeIt it(path); it != INVALID; ++it) {
   728         addFront(it);
   729       }
   730     }
   731 
   732   };
   733 
   734   /// \brief A structure for representing directed paths in a graph.
   735   ///
   736   /// A structure for representing directed path in a graph.
   737   /// \param Graph The graph type in which the path is.
   738   ///
   739   /// In a sense, the path can be treated as a list of edges. The
   740   /// lemon path type stores just this list. As a consequence it
   741   /// cannot enumerate the nodes in the path and the zero length paths
   742   /// cannot store the source.
   743   ///
   744   /// This implementation is completly static, so it cannot be
   745   /// modified exclude the assign an other path. It is intented to be
   746   /// used when you want to store a large number of paths because it is
   747   /// the most memory efficient path type in the lemon.
   748   template <typename _Graph>
   749   class StaticPath {
   750   public:
   751 
   752     typedef _Graph Graph;
   753     typedef typename Graph::Edge Edge;
   754 
   755     /// \brief Default constructor
   756     ///
   757     /// Default constructor
   758     StaticPath() : len(0), edges(0) {}
   759     
   760     /// \brief Template copy constructor
   761     ///
   762     /// This path can be initialized with any other path type. It just
   763     /// makes a copy of the given path.
   764     template <typename CPath>
   765     StaticPath(const CPath& cpath) : edges(0) {
   766       copyPath(*this, cpath);
   767     }
   768 
   769     /// \brief Destructor of the path
   770     ///
   771     /// Destructor of the path
   772     ~StaticPath() {
   773       if (edges) delete[] edges;
   774     }
   775 
   776     /// \brief Template copy assignment
   777     ///
   778     /// This path can be initialized with any other path type. It just
   779     /// makes a copy of the given path.
   780     template <typename CPath>
   781     StaticPath& operator=(const CPath& cpath) {
   782       copyPath(*this, cpath);
   783       return *this;
   784     }
   785 
   786     /// \brief Iterator class to iterate on the edges of the paths
   787     ///
   788     /// This class is used to iterate on the edges of the paths
   789     ///
   790     /// Of course it converts to Graph::Edge
   791     class EdgeIt {
   792       friend class StaticPath;
   793     public:
   794       /// Default constructor
   795       EdgeIt() {}
   796       /// Invalid constructor
   797       EdgeIt(Invalid) : path(0), idx(-1) {}
   798       /// Initializate the constructor to the first edge of path
   799       EdgeIt(const StaticPath &_path) 
   800         : path(&_path), idx(_path.empty() ? -1 : 0) {}
   801 
   802     private:
   803 
   804       /// Constructor with starting point
   805       EdgeIt(const StaticPath &_path, int _idx) 
   806         : idx(_idx), path(&_path) {}
   807 
   808     public:
   809 
   810       ///Conversion to Graph::Edge
   811       operator const Edge&() const {
   812         return path->nth(idx);
   813       }
   814 
   815       /// Next edge
   816       EdgeIt& operator++() { 
   817         ++idx;
   818         if (idx >= path->length()) idx = -1; 
   819         return *this; 
   820       }
   821 
   822       /// Comparison operator
   823       bool operator==(const EdgeIt& e) const { return idx==e.idx; }
   824       /// Comparison operator
   825       bool operator!=(const EdgeIt& e) const { return idx!=e.idx; }
   826       /// Comparison operator
   827       bool operator<(const EdgeIt& e) const { return idx<e.idx; }
   828 
   829     private:
   830       const StaticPath *path;
   831       int idx;
   832     };
   833 
   834     /// \brief Gives back the nth edge.
   835     ///
   836     /// \pre n is in the [0..length() - 1] range
   837     const Edge& nth(int n) const {
   838       return edges[n];
   839     }
   840 
   841     /// \brief Initializes edge iterator to point to the nth edge.
   842     EdgeIt nthIt(int n) const {
   843       return EdgeIt(*this, n);
   844     }
   845 
   846     /// \brief Gives back the length of the path.
   847     int length() const { return len; }
   848 
   849     /// \brief Returns true when the path is empty.
   850     int empty() const { return len == 0; }
   851 
   852     /// \break Erase all edge in the graph.
   853     void clear() {
   854       len = 0;
   855       if (edges) delete[] edges;
   856       edges = 0;
   857     }
   858 
   859     /// \brief Gives back the first edge of the path.
   860     const Edge& front() const {
   861       return edges[0];
   862     }
   863 
   864     /// \brief Gives back the last edge of the path.
   865     const Edge& back() const {
   866       return edges[len - 1];
   867     }
   868 
   869 
   870     typedef True BuildTag;
   871 
   872     template <typename CPath>
   873     void build(const CPath& path) {
   874       len = path.length();
   875       edges = new Edge[len];
   876       int index = 0;
   877       for (typename CPath::EdgeIt it(path); it != INVALID; ++it) {
   878         edges[index] = it;
   879         ++index;
   880       }
   881     }
   882 
   883     template <typename CPath>
   884     void buildRev(const CPath& path) {
   885       len = path.length();
   886       edges = new Edge[len];
   887       int index = len;
   888       for (typename CPath::RevEdgeIt it(path); it != INVALID; ++it) {
   889         --index;
   890         edges[index] = it;
   891       }
   892     }
   893 
   894   private:
   895     int len;
   896     Edge* edges;
   897   };
   898 
   899   ///@}
   900 
   901 } // namespace lemon
   902 
   903 #endif // LEMON_PATH_H