COIN-OR::LEMON - Graph Library

source: lemon/lemon/list_graph.h @ 313:64f8f7cc6168

Last change on this file since 313:64f8f7cc6168 was 313:64f8f7cc6168, checked in by Peter Kovacs <kpeter@…>, 10 years ago

Fix several doxygen warnings

File size: 41.9 KB
Line 
1/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 *
3 * This file is a part of LEMON, a generic C++ optimization library.
4 *
5 * Copyright (C) 2003-2008
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#ifndef LEMON_LIST_GRAPH_H
20#define LEMON_LIST_GRAPH_H
21
22///\ingroup graphs
23///\file
24///\brief ListDigraph, ListGraph classes.
25
26#include <lemon/core.h>
27#include <lemon/error.h>
28#include <lemon/bits/graph_extender.h>
29
30#include <vector>
31#include <list>
32
33namespace lemon {
34
35  class ListDigraphBase {
36
37  protected:
38    struct NodeT {
39      int first_in, first_out;
40      int prev, next;
41    };
42
43    struct ArcT {
44      int target, source;
45      int prev_in, prev_out;
46      int next_in, next_out;
47    };
48
49    std::vector<NodeT> nodes;
50
51    int first_node;
52
53    int first_free_node;
54
55    std::vector<ArcT> arcs;
56
57    int first_free_arc;
58
59  public:
60
61    typedef ListDigraphBase Digraph;
62
63    class Node {
64      friend class ListDigraphBase;
65    protected:
66
67      int id;
68      explicit Node(int pid) { id = pid;}
69
70    public:
71      Node() {}
72      Node (Invalid) { id = -1; }
73      bool operator==(const Node& node) const {return id == node.id;}
74      bool operator!=(const Node& node) const {return id != node.id;}
75      bool operator<(const Node& node) const {return id < node.id;}
76    };
77
78    class Arc {
79      friend class ListDigraphBase;
80    protected:
81
82      int id;
83      explicit Arc(int pid) { id = pid;}
84
85    public:
86      Arc() {}
87      Arc (Invalid) { id = -1; }
88      bool operator==(const Arc& arc) const {return id == arc.id;}
89      bool operator!=(const Arc& arc) const {return id != arc.id;}
90      bool operator<(const Arc& arc) const {return id < arc.id;}
91    };
92
93
94
95    ListDigraphBase()
96      : nodes(), first_node(-1),
97        first_free_node(-1), arcs(), first_free_arc(-1) {}
98
99
100    int maxNodeId() const { return nodes.size()-1; }
101    int maxArcId() const { return arcs.size()-1; }
102
103    Node source(Arc e) const { return Node(arcs[e.id].source); }
104    Node target(Arc e) const { return Node(arcs[e.id].target); }
105
106
107    void first(Node& node) const {
108      node.id = first_node;
109    }
110
111    void next(Node& node) const {
112      node.id = nodes[node.id].next;
113    }
114
115
116    void first(Arc& arc) const {
117      int n;
118      for(n = first_node;
119          n!=-1 && nodes[n].first_in == -1;
120          n = nodes[n].next) {}
121      arc.id = (n == -1) ? -1 : nodes[n].first_in;
122    }
123
124    void next(Arc& arc) const {
125      if (arcs[arc.id].next_in != -1) {
126        arc.id = arcs[arc.id].next_in;
127      } else {
128        int n;
129        for(n = nodes[arcs[arc.id].target].next;
130            n!=-1 && nodes[n].first_in == -1;
131            n = nodes[n].next) {}
132        arc.id = (n == -1) ? -1 : nodes[n].first_in;
133      }
134    }
135
136    void firstOut(Arc &e, const Node& v) const {
137      e.id = nodes[v.id].first_out;
138    }
139    void nextOut(Arc &e) const {
140      e.id=arcs[e.id].next_out;
141    }
142
143    void firstIn(Arc &e, const Node& v) const {
144      e.id = nodes[v.id].first_in;
145    }
146    void nextIn(Arc &e) const {
147      e.id=arcs[e.id].next_in;
148    }
149
150
151    static int id(Node v) { return v.id; }
152    static int id(Arc e) { return e.id; }
153
154    static Node nodeFromId(int id) { return Node(id);}
155    static Arc arcFromId(int id) { return Arc(id);}
156
157    bool valid(Node n) const {
158      return n.id >= 0 && n.id < static_cast<int>(nodes.size()) &&
159        nodes[n.id].prev != -2;
160    }
161
162    bool valid(Arc a) const {
163      return a.id >= 0 && a.id < static_cast<int>(arcs.size()) &&
164        arcs[a.id].prev_in != -2;
165    }
166
167    Node addNode() {
168      int n;
169
170      if(first_free_node==-1) {
171        n = nodes.size();
172        nodes.push_back(NodeT());
173      } else {
174        n = first_free_node;
175        first_free_node = nodes[n].next;
176      }
177
178      nodes[n].next = first_node;
179      if(first_node != -1) nodes[first_node].prev = n;
180      first_node = n;
181      nodes[n].prev = -1;
182
183      nodes[n].first_in = nodes[n].first_out = -1;
184
185      return Node(n);
186    }
187
188    Arc addArc(Node u, Node v) {
189      int n;
190
191      if (first_free_arc == -1) {
192        n = arcs.size();
193        arcs.push_back(ArcT());
194      } else {
195        n = first_free_arc;
196        first_free_arc = arcs[n].next_in;
197      }
198
199      arcs[n].source = u.id;
200      arcs[n].target = v.id;
201
202      arcs[n].next_out = nodes[u.id].first_out;
203      if(nodes[u.id].first_out != -1) {
204        arcs[nodes[u.id].first_out].prev_out = n;
205      }
206
207      arcs[n].next_in = nodes[v.id].first_in;
208      if(nodes[v.id].first_in != -1) {
209        arcs[nodes[v.id].first_in].prev_in = n;
210      }
211
212      arcs[n].prev_in = arcs[n].prev_out = -1;
213
214      nodes[u.id].first_out = nodes[v.id].first_in = n;
215
216      return Arc(n);
217    }
218
219    void erase(const Node& node) {
220      int n = node.id;
221
222      if(nodes[n].next != -1) {
223        nodes[nodes[n].next].prev = nodes[n].prev;
224      }
225
226      if(nodes[n].prev != -1) {
227        nodes[nodes[n].prev].next = nodes[n].next;
228      } else {
229        first_node = nodes[n].next;
230      }
231
232      nodes[n].next = first_free_node;
233      first_free_node = n;
234      nodes[n].prev = -2;
235
236    }
237
238    void erase(const Arc& arc) {
239      int n = arc.id;
240
241      if(arcs[n].next_in!=-1) {
242        arcs[arcs[n].next_in].prev_in = arcs[n].prev_in;
243      }
244
245      if(arcs[n].prev_in!=-1) {
246        arcs[arcs[n].prev_in].next_in = arcs[n].next_in;
247      } else {
248        nodes[arcs[n].target].first_in = arcs[n].next_in;
249      }
250
251
252      if(arcs[n].next_out!=-1) {
253        arcs[arcs[n].next_out].prev_out = arcs[n].prev_out;
254      }
255
256      if(arcs[n].prev_out!=-1) {
257        arcs[arcs[n].prev_out].next_out = arcs[n].next_out;
258      } else {
259        nodes[arcs[n].source].first_out = arcs[n].next_out;
260      }
261
262      arcs[n].next_in = first_free_arc;
263      first_free_arc = n;
264      arcs[n].prev_in = -2;
265    }
266
267    void clear() {
268      arcs.clear();
269      nodes.clear();
270      first_node = first_free_node = first_free_arc = -1;
271    }
272
273  protected:
274    void changeTarget(Arc e, Node n)
275    {
276      if(arcs[e.id].next_in != -1)
277        arcs[arcs[e.id].next_in].prev_in = arcs[e.id].prev_in;
278      if(arcs[e.id].prev_in != -1)
279        arcs[arcs[e.id].prev_in].next_in = arcs[e.id].next_in;
280      else nodes[arcs[e.id].target].first_in = arcs[e.id].next_in;
281      if (nodes[n.id].first_in != -1) {
282        arcs[nodes[n.id].first_in].prev_in = e.id;
283      }
284      arcs[e.id].target = n.id;
285      arcs[e.id].prev_in = -1;
286      arcs[e.id].next_in = nodes[n.id].first_in;
287      nodes[n.id].first_in = e.id;
288    }
289    void changeSource(Arc e, Node n)
290    {
291      if(arcs[e.id].next_out != -1)
292        arcs[arcs[e.id].next_out].prev_out = arcs[e.id].prev_out;
293      if(arcs[e.id].prev_out != -1)
294        arcs[arcs[e.id].prev_out].next_out = arcs[e.id].next_out;
295      else nodes[arcs[e.id].source].first_out = arcs[e.id].next_out;
296      if (nodes[n.id].first_out != -1) {
297        arcs[nodes[n.id].first_out].prev_out = e.id;
298      }
299      arcs[e.id].source = n.id;
300      arcs[e.id].prev_out = -1;
301      arcs[e.id].next_out = nodes[n.id].first_out;
302      nodes[n.id].first_out = e.id;
303    }
304
305  };
306
307  typedef DigraphExtender<ListDigraphBase> ExtendedListDigraphBase;
308
309  /// \addtogroup graphs
310  /// @{
311
312  ///A general directed graph structure.
313
314  ///\ref ListDigraph is a simple and fast <em>directed graph</em>
315  ///implementation based on static linked lists that are stored in
316  ///\c std::vector structures.
317  ///
318  ///It conforms to the \ref concepts::Digraph "Digraph concept" and it
319  ///also provides several useful additional functionalities.
320  ///Most of the member functions and nested classes are documented
321  ///only in the concept class.
322  ///
323  ///An important extra feature of this digraph implementation is that
324  ///its maps are real \ref concepts::ReferenceMap "reference map"s.
325  ///
326  ///\sa concepts::Digraph
327
328  class ListDigraph : public ExtendedListDigraphBase {
329  private:
330    ///ListDigraph is \e not copy constructible. Use copyDigraph() instead.
331
332    ///ListDigraph is \e not copy constructible. Use copyDigraph() instead.
333    ///
334    ListDigraph(const ListDigraph &) :ExtendedListDigraphBase() {};
335    ///\brief Assignment of ListDigraph to another one is \e not allowed.
336    ///Use copyDigraph() instead.
337
338    ///Assignment of ListDigraph to another one is \e not allowed.
339    ///Use copyDigraph() instead.
340    void operator=(const ListDigraph &) {}
341  public:
342
343    typedef ExtendedListDigraphBase Parent;
344
345    /// Constructor
346
347    /// Constructor.
348    ///
349    ListDigraph() {}
350
351    ///Add a new node to the digraph.
352
353    ///Add a new node to the digraph.
354    ///\return the new node.
355    Node addNode() { return Parent::addNode(); }
356
357    ///Add a new arc to the digraph.
358
359    ///Add a new arc to the digraph with source node \c s
360    ///and target node \c t.
361    ///\return the new arc.
362    Arc addArc(const Node& s, const Node& t) {
363      return Parent::addArc(s, t);
364    }
365
366    ///\brief Erase a node from the digraph.
367    ///
368    ///Erase a node from the digraph.
369    ///
370    void erase(const Node& n) { Parent::erase(n); }
371
372    ///\brief Erase an arc from the digraph.
373    ///
374    ///Erase an arc from the digraph.
375    ///
376    void erase(const Arc& a) { Parent::erase(a); }
377
378    /// Node validity check
379
380    /// This function gives back true if the given node is valid,
381    /// ie. it is a real node of the graph.
382    ///
383    /// \warning A Node pointing to a removed item
384    /// could become valid again later if new nodes are
385    /// added to the graph.
386    bool valid(Node n) const { return Parent::valid(n); }
387
388    /// Arc validity check
389
390    /// This function gives back true if the given arc is valid,
391    /// ie. it is a real arc of the graph.
392    ///
393    /// \warning An Arc pointing to a removed item
394    /// could become valid again later if new nodes are
395    /// added to the graph.
396    bool valid(Arc a) const { return Parent::valid(a); }
397
398    /// Change the target of \c a to \c n
399
400    /// Change the target of \c a to \c n
401    ///
402    ///\note The <tt>ArcIt</tt>s and <tt>OutArcIt</tt>s referencing
403    ///the changed arc remain valid. However <tt>InArcIt</tt>s are
404    ///invalidated.
405    ///
406    ///\warning This functionality cannot be used together with the Snapshot
407    ///feature.
408    void changeTarget(Arc a, Node n) {
409      Parent::changeTarget(a,n);
410    }
411    /// Change the source of \c a to \c n
412
413    /// Change the source of \c a to \c n
414    ///
415    ///\note The <tt>InArcIt</tt>s referencing the changed arc remain
416    ///valid. However the <tt>ArcIt</tt>s and <tt>OutArcIt</tt>s are
417    ///invalidated.
418    ///
419    ///\warning This functionality cannot be used together with the Snapshot
420    ///feature.
421    void changeSource(Arc a, Node n) {
422      Parent::changeSource(a,n);
423    }
424
425    /// Invert the direction of an arc.
426
427    ///\note The <tt>ArcIt</tt>s referencing the changed arc remain
428    ///valid. However <tt>OutArcIt</tt>s and <tt>InArcIt</tt>s are
429    ///invalidated.
430    ///
431    ///\warning This functionality cannot be used together with the Snapshot
432    ///feature.
433    void reverseArc(Arc e) {
434      Node t=target(e);
435      changeTarget(e,source(e));
436      changeSource(e,t);
437    }
438
439    /// Reserve memory for nodes.
440
441    /// Using this function it is possible to avoid the superfluous memory
442    /// allocation: if you know that the digraph you want to build will
443    /// be very large (e.g. it will contain millions of nodes and/or arcs)
444    /// then it is worth reserving space for this amount before starting
445    /// to build the digraph.
446    /// \sa reserveArc
447    void reserveNode(int n) { nodes.reserve(n); };
448
449    /// Reserve memory for arcs.
450
451    /// Using this function it is possible to avoid the superfluous memory
452    /// allocation: if you know that the digraph you want to build will
453    /// be very large (e.g. it will contain millions of nodes and/or arcs)
454    /// then it is worth reserving space for this amount before starting
455    /// to build the digraph.
456    /// \sa reserveNode
457    void reserveArc(int m) { arcs.reserve(m); };
458
459    ///Contract two nodes.
460
461    ///This function contracts two nodes.
462    ///Node \p b will be removed but instead of deleting
463    ///incident arcs, they will be joined to \p a.
464    ///The last parameter \p r controls whether to remove loops. \c true
465    ///means that loops will be removed.
466    ///
467    ///\note The <tt>ArcIt</tt>s referencing a moved arc remain
468    ///valid. However <tt>InArcIt</tt>s and <tt>OutArcIt</tt>s
469    ///may be invalidated.
470    ///
471    ///\warning This functionality cannot be used together with the Snapshot
472    ///feature.
473    void contract(Node a, Node b, bool r = true)
474    {
475      for(OutArcIt e(*this,b);e!=INVALID;) {
476        OutArcIt f=e;
477        ++f;
478        if(r && target(e)==a) erase(e);
479        else changeSource(e,a);
480        e=f;
481      }
482      for(InArcIt e(*this,b);e!=INVALID;) {
483        InArcIt f=e;
484        ++f;
485        if(r && source(e)==a) erase(e);
486        else changeTarget(e,a);
487        e=f;
488      }
489      erase(b);
490    }
491
492    ///Split a node.
493
494    ///This function splits a node. First a new node is added to the digraph,
495    ///then the source of each outgoing arc of \c n is moved to this new node.
496    ///If \c connect is \c true (this is the default value), then a new arc
497    ///from \c n to the newly created node is also added.
498    ///\return The newly created node.
499    ///
500    ///\note The <tt>ArcIt</tt>s referencing a moved arc remain
501    ///valid. However <tt>InArcIt</tt>s and <tt>OutArcIt</tt>s may
502    ///be invalidated.
503    ///
504    ///\warning This functionality cannot be used in conjunction with the
505    ///Snapshot feature.
506    Node split(Node n, bool connect = true) {
507      Node b = addNode();
508      for(OutArcIt e(*this,n);e!=INVALID;) {
509        OutArcIt f=e;
510        ++f;
511        changeSource(e,b);
512        e=f;
513      }
514      if (connect) addArc(n,b);
515      return b;
516    }
517
518    ///Split an arc.
519
520    ///This function splits an arc. First a new node \c b is added to
521    ///the digraph, then the original arc is re-targeted to \c
522    ///b. Finally an arc from \c b to the original target is added.
523    ///
524    ///\return The newly created node.
525    ///
526    ///\warning This functionality cannot be used together with the
527    ///Snapshot feature.
528    Node split(Arc e) {
529      Node b = addNode();
530      addArc(b,target(e));
531      changeTarget(e,b);
532      return b;
533    }
534
535    /// \brief Class to make a snapshot of the digraph and restore
536    /// it later.
537    ///
538    /// Class to make a snapshot of the digraph and restore it later.
539    ///
540    /// The newly added nodes and arcs can be removed using the
541    /// restore() function.
542    ///
543    /// \warning Arc and node deletions and other modifications (e.g.
544    /// contracting, splitting, reversing arcs or nodes) cannot be
545    /// restored. These events invalidate the snapshot.
546    class Snapshot {
547    protected:
548
549      typedef Parent::NodeNotifier NodeNotifier;
550
551      class NodeObserverProxy : public NodeNotifier::ObserverBase {
552      public:
553
554        NodeObserverProxy(Snapshot& _snapshot)
555          : snapshot(_snapshot) {}
556
557        using NodeNotifier::ObserverBase::attach;
558        using NodeNotifier::ObserverBase::detach;
559        using NodeNotifier::ObserverBase::attached;
560
561      protected:
562
563        virtual void add(const Node& node) {
564          snapshot.addNode(node);
565        }
566        virtual void add(const std::vector<Node>& nodes) {
567          for (int i = nodes.size() - 1; i >= 0; ++i) {
568            snapshot.addNode(nodes[i]);
569          }
570        }
571        virtual void erase(const Node& node) {
572          snapshot.eraseNode(node);
573        }
574        virtual void erase(const std::vector<Node>& nodes) {
575          for (int i = 0; i < int(nodes.size()); ++i) {
576            snapshot.eraseNode(nodes[i]);
577          }
578        }
579        virtual void build() {
580          Node node;
581          std::vector<Node> nodes;
582          for (notifier()->first(node); node != INVALID;
583               notifier()->next(node)) {
584            nodes.push_back(node);
585          }
586          for (int i = nodes.size() - 1; i >= 0; --i) {
587            snapshot.addNode(nodes[i]);
588          }
589        }
590        virtual void clear() {
591          Node node;
592          for (notifier()->first(node); node != INVALID;
593               notifier()->next(node)) {
594            snapshot.eraseNode(node);
595          }
596        }
597
598        Snapshot& snapshot;
599      };
600
601      class ArcObserverProxy : public ArcNotifier::ObserverBase {
602      public:
603
604        ArcObserverProxy(Snapshot& _snapshot)
605          : snapshot(_snapshot) {}
606
607        using ArcNotifier::ObserverBase::attach;
608        using ArcNotifier::ObserverBase::detach;
609        using ArcNotifier::ObserverBase::attached;
610
611      protected:
612
613        virtual void add(const Arc& arc) {
614          snapshot.addArc(arc);
615        }
616        virtual void add(const std::vector<Arc>& arcs) {
617          for (int i = arcs.size() - 1; i >= 0; ++i) {
618            snapshot.addArc(arcs[i]);
619          }
620        }
621        virtual void erase(const Arc& arc) {
622          snapshot.eraseArc(arc);
623        }
624        virtual void erase(const std::vector<Arc>& arcs) {
625          for (int i = 0; i < int(arcs.size()); ++i) {
626            snapshot.eraseArc(arcs[i]);
627          }
628        }
629        virtual void build() {
630          Arc arc;
631          std::vector<Arc> arcs;
632          for (notifier()->first(arc); arc != INVALID;
633               notifier()->next(arc)) {
634            arcs.push_back(arc);
635          }
636          for (int i = arcs.size() - 1; i >= 0; --i) {
637            snapshot.addArc(arcs[i]);
638          }
639        }
640        virtual void clear() {
641          Arc arc;
642          for (notifier()->first(arc); arc != INVALID;
643               notifier()->next(arc)) {
644            snapshot.eraseArc(arc);
645          }
646        }
647
648        Snapshot& snapshot;
649      };
650
651      ListDigraph *digraph;
652
653      NodeObserverProxy node_observer_proxy;
654      ArcObserverProxy arc_observer_proxy;
655
656      std::list<Node> added_nodes;
657      std::list<Arc> added_arcs;
658
659
660      void addNode(const Node& node) {
661        added_nodes.push_front(node);
662      }
663      void eraseNode(const Node& node) {
664        std::list<Node>::iterator it =
665          std::find(added_nodes.begin(), added_nodes.end(), node);
666        if (it == added_nodes.end()) {
667          clear();
668          arc_observer_proxy.detach();
669          throw NodeNotifier::ImmediateDetach();
670        } else {
671          added_nodes.erase(it);
672        }
673      }
674
675      void addArc(const Arc& arc) {
676        added_arcs.push_front(arc);
677      }
678      void eraseArc(const Arc& arc) {
679        std::list<Arc>::iterator it =
680          std::find(added_arcs.begin(), added_arcs.end(), arc);
681        if (it == added_arcs.end()) {
682          clear();
683          node_observer_proxy.detach();
684          throw ArcNotifier::ImmediateDetach();
685        } else {
686          added_arcs.erase(it);
687        }
688      }
689
690      void attach(ListDigraph &_digraph) {
691        digraph = &_digraph;
692        node_observer_proxy.attach(digraph->notifier(Node()));
693        arc_observer_proxy.attach(digraph->notifier(Arc()));
694      }
695
696      void detach() {
697        node_observer_proxy.detach();
698        arc_observer_proxy.detach();
699      }
700
701      bool attached() const {
702        return node_observer_proxy.attached();
703      }
704
705      void clear() {
706        added_nodes.clear();
707        added_arcs.clear();
708      }
709
710    public:
711
712      /// \brief Default constructor.
713      ///
714      /// Default constructor.
715      /// To actually make a snapshot you must call save().
716      Snapshot()
717        : digraph(0), node_observer_proxy(*this),
718          arc_observer_proxy(*this) {}
719
720      /// \brief Constructor that immediately makes a snapshot.
721      ///
722      /// This constructor immediately makes a snapshot of the digraph.
723      /// \param _digraph The digraph we make a snapshot of.
724      Snapshot(ListDigraph &_digraph)
725        : node_observer_proxy(*this),
726          arc_observer_proxy(*this) {
727        attach(_digraph);
728      }
729
730      /// \brief Make a snapshot.
731      ///
732      /// Make a snapshot of the digraph.
733      ///
734      /// This function can be called more than once. In case of a repeated
735      /// call, the previous snapshot gets lost.
736      /// \param _digraph The digraph we make the snapshot of.
737      void save(ListDigraph &_digraph) {
738        if (attached()) {
739          detach();
740          clear();
741        }
742        attach(_digraph);
743      }
744
745      /// \brief Undo the changes until the last snapshot.
746      //
747      /// Undo the changes until the last snapshot created by save().
748      void restore() {
749        detach();
750        for(std::list<Arc>::iterator it = added_arcs.begin();
751            it != added_arcs.end(); ++it) {
752          digraph->erase(*it);
753        }
754        for(std::list<Node>::iterator it = added_nodes.begin();
755            it != added_nodes.end(); ++it) {
756          digraph->erase(*it);
757        }
758        clear();
759      }
760
761      /// \brief Gives back true when the snapshot is valid.
762      ///
763      /// Gives back true when the snapshot is valid.
764      bool valid() const {
765        return attached();
766      }
767    };
768
769  };
770
771  ///@}
772
773  class ListGraphBase {
774
775  protected:
776
777    struct NodeT {
778      int first_out;
779      int prev, next;
780    };
781
782    struct ArcT {
783      int target;
784      int prev_out, next_out;
785    };
786
787    std::vector<NodeT> nodes;
788
789    int first_node;
790
791    int first_free_node;
792
793    std::vector<ArcT> arcs;
794
795    int first_free_arc;
796
797  public:
798
799    typedef ListGraphBase Digraph;
800
801    class Node;
802    class Arc;
803    class Edge;
804
805    class Node {
806      friend class ListGraphBase;
807    protected:
808
809      int id;
810      explicit Node(int pid) { id = pid;}
811
812    public:
813      Node() {}
814      Node (Invalid) { id = -1; }
815      bool operator==(const Node& node) const {return id == node.id;}
816      bool operator!=(const Node& node) const {return id != node.id;}
817      bool operator<(const Node& node) const {return id < node.id;}
818    };
819
820    class Edge {
821      friend class ListGraphBase;
822    protected:
823
824      int id;
825      explicit Edge(int pid) { id = pid;}
826
827    public:
828      Edge() {}
829      Edge (Invalid) { id = -1; }
830      bool operator==(const Edge& edge) const {return id == edge.id;}
831      bool operator!=(const Edge& edge) const {return id != edge.id;}
832      bool operator<(const Edge& edge) const {return id < edge.id;}
833    };
834
835    class Arc {
836      friend class ListGraphBase;
837    protected:
838
839      int id;
840      explicit Arc(int pid) { id = pid;}
841
842    public:
843      operator Edge() const {
844        return id != -1 ? edgeFromId(id / 2) : INVALID;
845      }
846
847      Arc() {}
848      Arc (Invalid) { id = -1; }
849      bool operator==(const Arc& arc) const {return id == arc.id;}
850      bool operator!=(const Arc& arc) const {return id != arc.id;}
851      bool operator<(const Arc& arc) const {return id < arc.id;}
852    };
853
854
855
856    ListGraphBase()
857      : nodes(), first_node(-1),
858        first_free_node(-1), arcs(), first_free_arc(-1) {}
859
860
861    int maxNodeId() const { return nodes.size()-1; }
862    int maxEdgeId() const { return arcs.size() / 2 - 1; }
863    int maxArcId() const { return arcs.size()-1; }
864
865    Node source(Arc e) const { return Node(arcs[e.id ^ 1].target); }
866    Node target(Arc e) const { return Node(arcs[e.id].target); }
867
868    Node u(Edge e) const { return Node(arcs[2 * e.id].target); }
869    Node v(Edge e) const { return Node(arcs[2 * e.id + 1].target); }
870
871    static bool direction(Arc e) {
872      return (e.id & 1) == 1;
873    }
874
875    static Arc direct(Edge e, bool d) {
876      return Arc(e.id * 2 + (d ? 1 : 0));
877    }
878
879    void first(Node& node) const {
880      node.id = first_node;
881    }
882
883    void next(Node& node) const {
884      node.id = nodes[node.id].next;
885    }
886
887    void first(Arc& e) const {
888      int n = first_node;
889      while (n != -1 && nodes[n].first_out == -1) {
890        n = nodes[n].next;
891      }
892      e.id = (n == -1) ? -1 : nodes[n].first_out;
893    }
894
895    void next(Arc& e) const {
896      if (arcs[e.id].next_out != -1) {
897        e.id = arcs[e.id].next_out;
898      } else {
899        int n = nodes[arcs[e.id ^ 1].target].next;
900        while(n != -1 && nodes[n].first_out == -1) {
901          n = nodes[n].next;
902        }
903        e.id = (n == -1) ? -1 : nodes[n].first_out;
904      }
905    }
906
907    void first(Edge& e) const {
908      int n = first_node;
909      while (n != -1) {
910        e.id = nodes[n].first_out;
911        while ((e.id & 1) != 1) {
912          e.id = arcs[e.id].next_out;
913        }
914        if (e.id != -1) {
915          e.id /= 2;
916          return;
917        }
918        n = nodes[n].next;
919      }
920      e.id = -1;
921    }
922
923    void next(Edge& e) const {
924      int n = arcs[e.id * 2].target;
925      e.id = arcs[(e.id * 2) | 1].next_out;
926      while ((e.id & 1) != 1) {
927        e.id = arcs[e.id].next_out;
928      }
929      if (e.id != -1) {
930        e.id /= 2;
931        return;
932      }
933      n = nodes[n].next;
934      while (n != -1) {
935        e.id = nodes[n].first_out;
936        while ((e.id & 1) != 1) {
937          e.id = arcs[e.id].next_out;
938        }
939        if (e.id != -1) {
940          e.id /= 2;
941          return;
942        }
943        n = nodes[n].next;
944      }
945      e.id = -1;
946    }
947
948    void firstOut(Arc &e, const Node& v) const {
949      e.id = nodes[v.id].first_out;
950    }
951    void nextOut(Arc &e) const {
952      e.id = arcs[e.id].next_out;
953    }
954
955    void firstIn(Arc &e, const Node& v) const {
956      e.id = ((nodes[v.id].first_out) ^ 1);
957      if (e.id == -2) e.id = -1;
958    }
959    void nextIn(Arc &e) const {
960      e.id = ((arcs[e.id ^ 1].next_out) ^ 1);
961      if (e.id == -2) e.id = -1;
962    }
963
964    void firstInc(Edge &e, bool& d, const Node& v) const {
965      int a = nodes[v.id].first_out;
966      if (a != -1 ) {
967        e.id = a / 2;
968        d = ((a & 1) == 1);
969      } else {
970        e.id = -1;
971        d = true;
972      }
973    }
974    void nextInc(Edge &e, bool& d) const {
975      int a = (arcs[(e.id * 2) | (d ? 1 : 0)].next_out);
976      if (a != -1 ) {
977        e.id = a / 2;
978        d = ((a & 1) == 1);
979      } else {
980        e.id = -1;
981        d = true;
982      }
983    }
984
985    static int id(Node v) { return v.id; }
986    static int id(Arc e) { return e.id; }
987    static int id(Edge e) { return e.id; }
988
989    static Node nodeFromId(int id) { return Node(id);}
990    static Arc arcFromId(int id) { return Arc(id);}
991    static Edge edgeFromId(int id) { return Edge(id);}
992
993    bool valid(Node n) const {
994      return n.id >= 0 && n.id < static_cast<int>(nodes.size()) &&
995        nodes[n.id].prev != -2;
996    }
997
998    bool valid(Arc a) const {
999      return a.id >= 0 && a.id < static_cast<int>(arcs.size()) &&
1000        arcs[a.id].prev_out != -2;
1001    }
1002
1003    bool valid(Edge e) const {
1004      return e.id >= 0 && 2 * e.id < static_cast<int>(arcs.size()) &&
1005        arcs[2 * e.id].prev_out != -2;
1006    }
1007
1008    Node addNode() {
1009      int n;
1010
1011      if(first_free_node==-1) {
1012        n = nodes.size();
1013        nodes.push_back(NodeT());
1014      } else {
1015        n = first_free_node;
1016        first_free_node = nodes[n].next;
1017      }
1018
1019      nodes[n].next = first_node;
1020      if (first_node != -1) nodes[first_node].prev = n;
1021      first_node = n;
1022      nodes[n].prev = -1;
1023
1024      nodes[n].first_out = -1;
1025
1026      return Node(n);
1027    }
1028
1029    Edge addEdge(Node u, Node v) {
1030      int n;
1031
1032      if (first_free_arc == -1) {
1033        n = arcs.size();
1034        arcs.push_back(ArcT());
1035        arcs.push_back(ArcT());
1036      } else {
1037        n = first_free_arc;
1038        first_free_arc = arcs[n].next_out;
1039      }
1040
1041      arcs[n].target = u.id;
1042      arcs[n | 1].target = v.id;
1043
1044      arcs[n].next_out = nodes[v.id].first_out;
1045      if (nodes[v.id].first_out != -1) {
1046        arcs[nodes[v.id].first_out].prev_out = n;
1047      }
1048      arcs[n].prev_out = -1;
1049      nodes[v.id].first_out = n;
1050
1051      arcs[n | 1].next_out = nodes[u.id].first_out;
1052      if (nodes[u.id].first_out != -1) {
1053        arcs[nodes[u.id].first_out].prev_out = (n | 1);
1054      }
1055      arcs[n | 1].prev_out = -1;
1056      nodes[u.id].first_out = (n | 1);
1057
1058      return Edge(n / 2);
1059    }
1060
1061    void erase(const Node& node) {
1062      int n = node.id;
1063
1064      if(nodes[n].next != -1) {
1065        nodes[nodes[n].next].prev = nodes[n].prev;
1066      }
1067
1068      if(nodes[n].prev != -1) {
1069        nodes[nodes[n].prev].next = nodes[n].next;
1070      } else {
1071        first_node = nodes[n].next;
1072      }
1073
1074      nodes[n].next = first_free_node;
1075      first_free_node = n;
1076      nodes[n].prev = -2;
1077    }
1078
1079    void erase(const Edge& edge) {
1080      int n = edge.id * 2;
1081
1082      if (arcs[n].next_out != -1) {
1083        arcs[arcs[n].next_out].prev_out = arcs[n].prev_out;
1084      }
1085
1086      if (arcs[n].prev_out != -1) {
1087        arcs[arcs[n].prev_out].next_out = arcs[n].next_out;
1088      } else {
1089        nodes[arcs[n | 1].target].first_out = arcs[n].next_out;
1090      }
1091
1092      if (arcs[n | 1].next_out != -1) {
1093        arcs[arcs[n | 1].next_out].prev_out = arcs[n | 1].prev_out;
1094      }
1095
1096      if (arcs[n | 1].prev_out != -1) {
1097        arcs[arcs[n | 1].prev_out].next_out = arcs[n | 1].next_out;
1098      } else {
1099        nodes[arcs[n].target].first_out = arcs[n | 1].next_out;
1100      }
1101
1102      arcs[n].next_out = first_free_arc;
1103      first_free_arc = n;
1104      arcs[n].prev_out = -2;
1105      arcs[n | 1].prev_out = -2;
1106
1107    }
1108
1109    void clear() {
1110      arcs.clear();
1111      nodes.clear();
1112      first_node = first_free_node = first_free_arc = -1;
1113    }
1114
1115  protected:
1116
1117    void changeV(Edge e, Node n) {
1118      if(arcs[2 * e.id].next_out != -1) {
1119        arcs[arcs[2 * e.id].next_out].prev_out = arcs[2 * e.id].prev_out;
1120      }
1121      if(arcs[2 * e.id].prev_out != -1) {
1122        arcs[arcs[2 * e.id].prev_out].next_out =
1123          arcs[2 * e.id].next_out;
1124      } else {
1125        nodes[arcs[(2 * e.id) | 1].target].first_out =
1126          arcs[2 * e.id].next_out;
1127      }
1128
1129      if (nodes[n.id].first_out != -1) {
1130        arcs[nodes[n.id].first_out].prev_out = 2 * e.id;
1131      }
1132      arcs[(2 * e.id) | 1].target = n.id;
1133      arcs[2 * e.id].prev_out = -1;
1134      arcs[2 * e.id].next_out = nodes[n.id].first_out;
1135      nodes[n.id].first_out = 2 * e.id;
1136    }
1137
1138    void changeU(Edge e, Node n) {
1139      if(arcs[(2 * e.id) | 1].next_out != -1) {
1140        arcs[arcs[(2 * e.id) | 1].next_out].prev_out =
1141          arcs[(2 * e.id) | 1].prev_out;
1142      }
1143      if(arcs[(2 * e.id) | 1].prev_out != -1) {
1144        arcs[arcs[(2 * e.id) | 1].prev_out].next_out =
1145          arcs[(2 * e.id) | 1].next_out;
1146      } else {
1147        nodes[arcs[2 * e.id].target].first_out =
1148          arcs[(2 * e.id) | 1].next_out;
1149      }
1150
1151      if (nodes[n.id].first_out != -1) {
1152        arcs[nodes[n.id].first_out].prev_out = ((2 * e.id) | 1);
1153      }
1154      arcs[2 * e.id].target = n.id;
1155      arcs[(2 * e.id) | 1].prev_out = -1;
1156      arcs[(2 * e.id) | 1].next_out = nodes[n.id].first_out;
1157      nodes[n.id].first_out = ((2 * e.id) | 1);
1158    }
1159
1160  };
1161
1162  typedef GraphExtender<ListGraphBase> ExtendedListGraphBase;
1163
1164
1165  /// \addtogroup graphs
1166  /// @{
1167
1168  ///A general undirected graph structure.
1169
1170  ///\ref ListGraph is a simple and fast <em>undirected graph</em>
1171  ///implementation based on static linked lists that are stored in
1172  ///\c std::vector structures.
1173  ///
1174  ///It conforms to the \ref concepts::Graph "Graph concept" and it
1175  ///also provides several useful additional functionalities.
1176  ///Most of the member functions and nested classes are documented
1177  ///only in the concept class.
1178  ///
1179  ///An important extra feature of this graph implementation is that
1180  ///its maps are real \ref concepts::ReferenceMap "reference map"s.
1181  ///
1182  ///\sa concepts::Graph
1183
1184  class ListGraph : public ExtendedListGraphBase {
1185  private:
1186    ///ListGraph is \e not copy constructible. Use copyGraph() instead.
1187
1188    ///ListGraph is \e not copy constructible. Use copyGraph() instead.
1189    ///
1190    ListGraph(const ListGraph &) :ExtendedListGraphBase()  {};
1191    ///\brief Assignment of ListGraph to another one is \e not allowed.
1192    ///Use copyGraph() instead.
1193
1194    ///Assignment of ListGraph to another one is \e not allowed.
1195    ///Use copyGraph() instead.
1196    void operator=(const ListGraph &) {}
1197  public:
1198    /// Constructor
1199
1200    /// Constructor.
1201    ///
1202    ListGraph() {}
1203
1204    typedef ExtendedListGraphBase Parent;
1205
1206    typedef Parent::OutArcIt IncEdgeIt;
1207
1208    /// \brief Add a new node to the graph.
1209    ///
1210    /// Add a new node to the graph.
1211    /// \return the new node.
1212    Node addNode() { return Parent::addNode(); }
1213
1214    /// \brief Add a new edge to the graph.
1215    ///
1216    /// Add a new edge to the graph with source node \c s
1217    /// and target node \c t.
1218    /// \return the new edge.
1219    Edge addEdge(const Node& s, const Node& t) {
1220      return Parent::addEdge(s, t);
1221    }
1222
1223    /// \brief Erase a node from the graph.
1224    ///
1225    /// Erase a node from the graph.
1226    ///
1227    void erase(const Node& n) { Parent::erase(n); }
1228
1229    /// \brief Erase an edge from the graph.
1230    ///
1231    /// Erase an edge from the graph.
1232    ///
1233    void erase(const Edge& e) { Parent::erase(e); }
1234    /// Node validity check
1235
1236    /// This function gives back true if the given node is valid,
1237    /// ie. it is a real node of the graph.
1238    ///
1239    /// \warning A Node pointing to a removed item
1240    /// could become valid again later if new nodes are
1241    /// added to the graph.
1242    bool valid(Node n) const { return Parent::valid(n); }
1243    /// Arc validity check
1244
1245    /// This function gives back true if the given arc is valid,
1246    /// ie. it is a real arc of the graph.
1247    ///
1248    /// \warning An Arc pointing to a removed item
1249    /// could become valid again later if new edges are
1250    /// added to the graph.
1251    bool valid(Arc a) const { return Parent::valid(a); }
1252    /// Edge validity check
1253
1254    /// This function gives back true if the given edge is valid,
1255    /// ie. it is a real arc of the graph.
1256    ///
1257    /// \warning A Edge pointing to a removed item
1258    /// could become valid again later if new edges are
1259    /// added to the graph.
1260    bool valid(Edge e) const { return Parent::valid(e); }
1261    /// \brief Change the end \c u of \c e to \c n
1262    ///
1263    /// This function changes the end \c u of \c e to node \c n.
1264    ///
1265    ///\note The <tt>EdgeIt</tt>s and <tt>ArcIt</tt>s referencing the
1266    ///changed edge are invalidated and if the changed node is the
1267    ///base node of an iterator then this iterator is also
1268    ///invalidated.
1269    ///
1270    ///\warning This functionality cannot be used together with the
1271    ///Snapshot feature.
1272    void changeU(Edge e, Node n) {
1273      Parent::changeU(e,n);
1274    }
1275    /// \brief Change the end \c v of \c e to \c n
1276    ///
1277    /// This function changes the end \c v of \c e to \c n.
1278    ///
1279    ///\note The <tt>EdgeIt</tt>s referencing the changed edge remain
1280    ///valid, however <tt>ArcIt</tt>s and if the changed node is the
1281    ///base node of an iterator then this iterator is invalidated.
1282    ///
1283    ///\warning This functionality cannot be used together with the
1284    ///Snapshot feature.
1285    void changeV(Edge e, Node n) {
1286      Parent::changeV(e,n);
1287    }
1288    /// \brief Contract two nodes.
1289    ///
1290    /// This function contracts two nodes.
1291    /// Node \p b will be removed but instead of deleting
1292    /// its neighboring arcs, they will be joined to \p a.
1293    /// The last parameter \p r controls whether to remove loops. \c true
1294    /// means that loops will be removed.
1295    ///
1296    /// \note The <tt>ArcIt</tt>s referencing a moved arc remain
1297    /// valid.
1298    ///
1299    ///\warning This functionality cannot be used together with the
1300    ///Snapshot feature.
1301    void contract(Node a, Node b, bool r = true) {
1302      for(IncEdgeIt e(*this, b); e!=INVALID;) {
1303        IncEdgeIt f = e; ++f;
1304        if (r && runningNode(e) == a) {
1305          erase(e);
1306        } else if (u(e) == b) {
1307          changeU(e, a);
1308        } else {
1309          changeV(e, a);
1310        }
1311        e = f;
1312      }
1313      erase(b);
1314    }
1315
1316
1317    /// \brief Class to make a snapshot of the graph and restore
1318    /// it later.
1319    ///
1320    /// Class to make a snapshot of the graph and restore it later.
1321    ///
1322    /// The newly added nodes and edges can be removed
1323    /// using the restore() function.
1324    ///
1325    /// \warning Edge and node deletions and other modifications
1326    /// (e.g. changing nodes of edges, contracting nodes) cannot be
1327    /// restored. These events invalidate the snapshot.
1328    class Snapshot {
1329    protected:
1330
1331      typedef Parent::NodeNotifier NodeNotifier;
1332
1333      class NodeObserverProxy : public NodeNotifier::ObserverBase {
1334      public:
1335
1336        NodeObserverProxy(Snapshot& _snapshot)
1337          : snapshot(_snapshot) {}
1338
1339        using NodeNotifier::ObserverBase::attach;
1340        using NodeNotifier::ObserverBase::detach;
1341        using NodeNotifier::ObserverBase::attached;
1342
1343      protected:
1344
1345        virtual void add(const Node& node) {
1346          snapshot.addNode(node);
1347        }
1348        virtual void add(const std::vector<Node>& nodes) {
1349          for (int i = nodes.size() - 1; i >= 0; ++i) {
1350            snapshot.addNode(nodes[i]);
1351          }
1352        }
1353        virtual void erase(const Node& node) {
1354          snapshot.eraseNode(node);
1355        }
1356        virtual void erase(const std::vector<Node>& nodes) {
1357          for (int i = 0; i < int(nodes.size()); ++i) {
1358            snapshot.eraseNode(nodes[i]);
1359          }
1360        }
1361        virtual void build() {
1362          Node node;
1363          std::vector<Node> nodes;
1364          for (notifier()->first(node); node != INVALID;
1365               notifier()->next(node)) {
1366            nodes.push_back(node);
1367          }
1368          for (int i = nodes.size() - 1; i >= 0; --i) {
1369            snapshot.addNode(nodes[i]);
1370          }
1371        }
1372        virtual void clear() {
1373          Node node;
1374          for (notifier()->first(node); node != INVALID;
1375               notifier()->next(node)) {
1376            snapshot.eraseNode(node);
1377          }
1378        }
1379
1380        Snapshot& snapshot;
1381      };
1382
1383      class EdgeObserverProxy : public EdgeNotifier::ObserverBase {
1384      public:
1385
1386        EdgeObserverProxy(Snapshot& _snapshot)
1387          : snapshot(_snapshot) {}
1388
1389        using EdgeNotifier::ObserverBase::attach;
1390        using EdgeNotifier::ObserverBase::detach;
1391        using EdgeNotifier::ObserverBase::attached;
1392
1393      protected:
1394
1395        virtual void add(const Edge& edge) {
1396          snapshot.addEdge(edge);
1397        }
1398        virtual void add(const std::vector<Edge>& edges) {
1399          for (int i = edges.size() - 1; i >= 0; ++i) {
1400            snapshot.addEdge(edges[i]);
1401          }
1402        }
1403        virtual void erase(const Edge& edge) {
1404          snapshot.eraseEdge(edge);
1405        }
1406        virtual void erase(const std::vector<Edge>& edges) {
1407          for (int i = 0; i < int(edges.size()); ++i) {
1408            snapshot.eraseEdge(edges[i]);
1409          }
1410        }
1411        virtual void build() {
1412          Edge edge;
1413          std::vector<Edge> edges;
1414          for (notifier()->first(edge); edge != INVALID;
1415               notifier()->next(edge)) {
1416            edges.push_back(edge);
1417          }
1418          for (int i = edges.size() - 1; i >= 0; --i) {
1419            snapshot.addEdge(edges[i]);
1420          }
1421        }
1422        virtual void clear() {
1423          Edge edge;
1424          for (notifier()->first(edge); edge != INVALID;
1425               notifier()->next(edge)) {
1426            snapshot.eraseEdge(edge);
1427          }
1428        }
1429
1430        Snapshot& snapshot;
1431      };
1432
1433      ListGraph *graph;
1434
1435      NodeObserverProxy node_observer_proxy;
1436      EdgeObserverProxy edge_observer_proxy;
1437
1438      std::list<Node> added_nodes;
1439      std::list<Edge> added_edges;
1440
1441
1442      void addNode(const Node& node) {
1443        added_nodes.push_front(node);
1444      }
1445      void eraseNode(const Node& node) {
1446        std::list<Node>::iterator it =
1447          std::find(added_nodes.begin(), added_nodes.end(), node);
1448        if (it == added_nodes.end()) {
1449          clear();
1450          edge_observer_proxy.detach();
1451          throw NodeNotifier::ImmediateDetach();
1452        } else {
1453          added_nodes.erase(it);
1454        }
1455      }
1456
1457      void addEdge(const Edge& edge) {
1458        added_edges.push_front(edge);
1459      }
1460      void eraseEdge(const Edge& edge) {
1461        std::list<Edge>::iterator it =
1462          std::find(added_edges.begin(), added_edges.end(), edge);
1463        if (it == added_edges.end()) {
1464          clear();
1465          node_observer_proxy.detach();
1466          throw EdgeNotifier::ImmediateDetach();
1467        } else {
1468          added_edges.erase(it);
1469        }
1470      }
1471
1472      void attach(ListGraph &_graph) {
1473        graph = &_graph;
1474        node_observer_proxy.attach(graph->notifier(Node()));
1475        edge_observer_proxy.attach(graph->notifier(Edge()));
1476      }
1477
1478      void detach() {
1479        node_observer_proxy.detach();
1480        edge_observer_proxy.detach();
1481      }
1482
1483      bool attached() const {
1484        return node_observer_proxy.attached();
1485      }
1486
1487      void clear() {
1488        added_nodes.clear();
1489        added_edges.clear();
1490      }
1491
1492    public:
1493
1494      /// \brief Default constructor.
1495      ///
1496      /// Default constructor.
1497      /// To actually make a snapshot you must call save().
1498      Snapshot()
1499        : graph(0), node_observer_proxy(*this),
1500          edge_observer_proxy(*this) {}
1501
1502      /// \brief Constructor that immediately makes a snapshot.
1503      ///
1504      /// This constructor immediately makes a snapshot of the graph.
1505      /// \param _graph The graph we make a snapshot of.
1506      Snapshot(ListGraph &_graph)
1507        : node_observer_proxy(*this),
1508          edge_observer_proxy(*this) {
1509        attach(_graph);
1510      }
1511
1512      /// \brief Make a snapshot.
1513      ///
1514      /// Make a snapshot of the graph.
1515      ///
1516      /// This function can be called more than once. In case of a repeated
1517      /// call, the previous snapshot gets lost.
1518      /// \param _graph The graph we make the snapshot of.
1519      void save(ListGraph &_graph) {
1520        if (attached()) {
1521          detach();
1522          clear();
1523        }
1524        attach(_graph);
1525      }
1526
1527      /// \brief Undo the changes until the last snapshot.
1528      //
1529      /// Undo the changes until the last snapshot created by save().
1530      void restore() {
1531        detach();
1532        for(std::list<Edge>::iterator it = added_edges.begin();
1533            it != added_edges.end(); ++it) {
1534          graph->erase(*it);
1535        }
1536        for(std::list<Node>::iterator it = added_nodes.begin();
1537            it != added_nodes.end(); ++it) {
1538          graph->erase(*it);
1539        }
1540        clear();
1541      }
1542
1543      /// \brief Gives back true when the snapshot is valid.
1544      ///
1545      /// Gives back true when the snapshot is valid.
1546      bool valid() const {
1547        return attached();
1548      }
1549    };
1550  };
1551
1552  /// @}
1553} //namespace lemon
1554
1555
1556#endif
Note: See TracBrowser for help on using the repository browser.