COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/path.h @ 2508:c86db0f7f917

Last change on this file since 2508:c86db0f7f917 was 2419:6a567c0f1214, checked in by Akos Ladanyi, 17 years ago

Added SimplePath::front().

File size: 23.8 KB
Line 
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
34namespace 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        : idx(_idx), path(&_path) {}
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
Note: See TracBrowser for help on using the repository browser.