COIN-OR::LEMON - Graph Library

source: lemon-1.2/lemon/list_graph.h @ 863:a93f1a27d831

Last change on this file since 863:a93f1a27d831 was 788:c92296660262, checked in by Alpar Juttner <alpar@…>, 10 years ago

Merge

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