COIN-OR::LEMON - Graph Library

source: lemon-main/lemon/list_graph.h @ 234:ad6b8c47bd56

Last change on this file since 234:ad6b8c47bd56 was 234:ad6b8c47bd56, checked in by Balazs Dezso <deba@…>, 16 years ago

Erase in the documentation of list graphs

File size: 43.1 KB
RevLine 
[209]1/* -*- mode: C++; indent-tabs-mode: nil; -*-
[39]2 *
[209]3 * This file is a part of LEMON, a generic C++ optimization library.
[39]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
[57]19#ifndef LEMON_LIST_GRAPH_H
20#define LEMON_LIST_GRAPH_H
21
22///\ingroup graphs
23///\file
24///\brief ListDigraph, ListGraph classes.
25
[220]26#include <lemon/core.h>
27#include <lemon/error.h>
[57]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    };
[209]42
[57]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;
[209]58
[57]59  public:
[209]60
[57]61    typedef ListDigraphBase Digraph;
[209]62
[57]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),
[209]97        first_free_node(-1), arcs(), first_free_arc(-1) {}
[57]98
[209]99
100    int maxNodeId() const { return nodes.size()-1; }
[57]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
[209]107    void first(Node& node) const {
[57]108      node.id = first_node;
109    }
110
111    void next(Node& node) const {
112      node.id = nodes[node.id].next;
113    }
114
115
[209]116    void first(Arc& arc) const {
[57]117      int n;
[209]118      for(n = first_node;
119          n!=-1 && nodes[n].first_in == -1;
120          n = nodes[n].next) {}
[73]121      arc.id = (n == -1) ? -1 : nodes[n].first_in;
[57]122    }
123
124    void next(Arc& arc) const {
125      if (arcs[arc.id].next_in != -1) {
[209]126        arc.id = arcs[arc.id].next_in;
[57]127      } else {
[209]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      }
[57]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
[209]150
[57]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
[209]157    bool valid(Node n) const {
158      return n.id >= 0 && n.id < static_cast<int>(nodes.size()) &&
159        nodes[n.id].prev != -2;
[149]160    }
161
[209]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;
[149]165    }
166
[209]167    Node addNode() {
[57]168      int n;
[209]169
[57]170      if(first_free_node==-1) {
[209]171        n = nodes.size();
172        nodes.push_back(NodeT());
[57]173      } else {
[209]174        n = first_free_node;
175        first_free_node = nodes[n].next;
[57]176      }
[209]177
[57]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;
[209]182
[57]183      nodes[n].first_in = nodes[n].first_out = -1;
[209]184
[57]185      return Node(n);
186    }
[209]187
[57]188    Arc addArc(Node u, Node v) {
[209]189      int n;
[57]190
191      if (first_free_arc == -1) {
[209]192        n = arcs.size();
193        arcs.push_back(ArcT());
[57]194      } else {
[209]195        n = first_free_arc;
196        first_free_arc = arcs[n].next_in;
[57]197      }
[209]198
199      arcs[n].source = u.id;
[57]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) {
[209]204        arcs[nodes[u.id].first_out].prev_out = n;
[57]205      }
[209]206
[57]207      arcs[n].next_in = nodes[v.id].first_in;
208      if(nodes[v.id].first_in != -1) {
[209]209        arcs[nodes[v.id].first_in].prev_in = n;
[57]210      }
[209]211
[57]212      arcs[n].prev_in = arcs[n].prev_out = -1;
[209]213
[57]214      nodes[u.id].first_out = nodes[v.id].first_in = n;
215
216      return Arc(n);
217    }
[209]218
[57]219    void erase(const Node& node) {
220      int n = node.id;
[209]221
[57]222      if(nodes[n].next != -1) {
[209]223        nodes[nodes[n].next].prev = nodes[n].prev;
[57]224      }
[209]225
[57]226      if(nodes[n].prev != -1) {
[209]227        nodes[nodes[n].prev].next = nodes[n].next;
[57]228      } else {
[209]229        first_node = nodes[n].next;
[57]230      }
[209]231
[57]232      nodes[n].next = first_free_node;
233      first_free_node = n;
[149]234      nodes[n].prev = -2;
[57]235
236    }
[209]237
[57]238    void erase(const Arc& arc) {
239      int n = arc.id;
[209]240
[57]241      if(arcs[n].next_in!=-1) {
[209]242        arcs[arcs[n].next_in].prev_in = arcs[n].prev_in;
[57]243      }
244
245      if(arcs[n].prev_in!=-1) {
[209]246        arcs[arcs[n].prev_in].next_in = arcs[n].next_in;
[57]247      } else {
[209]248        nodes[arcs[n].target].first_in = arcs[n].next_in;
[57]249      }
250
[209]251
[57]252      if(arcs[n].next_out!=-1) {
[209]253        arcs[arcs[n].next_out].prev_out = arcs[n].prev_out;
254      }
[57]255
256      if(arcs[n].prev_out!=-1) {
[209]257        arcs[arcs[n].prev_out].next_out = arcs[n].next_out;
[57]258      } else {
[209]259        nodes[arcs[n].source].first_out = arcs[n].next_out;
[57]260      }
[209]261
[57]262      arcs[n].next_in = first_free_arc;
[149]263      first_free_arc = n;
264      arcs[n].prev_in = -2;
[57]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:
[209]274    void changeTarget(Arc e, Node n)
[57]275    {
276      if(arcs[e.id].next_in != -1)
[209]277        arcs[arcs[e.id].next_in].prev_in = arcs[e.id].prev_in;
[57]278      if(arcs[e.id].prev_in != -1)
[209]279        arcs[arcs[e.id].prev_in].next_in = arcs[e.id].next_in;
[57]280      else nodes[arcs[e.id].target].first_in = arcs[e.id].next_in;
281      if (nodes[n.id].first_in != -1) {
[209]282        arcs[nodes[n.id].first_in].prev_in = e.id;
[57]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    }
[209]289    void changeSource(Arc e, Node n)
[57]290    {
291      if(arcs[e.id].next_out != -1)
[209]292        arcs[arcs[e.id].next_out].prev_out = arcs[e.id].prev_out;
[57]293      if(arcs[e.id].prev_out != -1)
[209]294        arcs[arcs[e.id].prev_out].next_out = arcs[e.id].next_out;
[57]295      else nodes[arcs[e.id].source].first_out = arcs[e.id].next_out;
296      if (nodes[n.id].first_out != -1) {
[209]297        arcs[nodes[n.id].first_out].prev_out = e.id;
[57]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
[73]309  /// \addtogroup graphs
[57]310  /// @{
311
[209]312  ///A general directed graph structure.
[57]313
[209]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.
[57]317  ///
318  ///It conforms to the \ref concepts::Digraph "Digraph concept" and it
[73]319  ///also provides several useful additional functionalities.
320  ///Most of the member functions and nested classes are documented
321  ///only in the concept class.
[57]322  ///
323  ///An important extra feature of this digraph implementation is that
324  ///its maps are real \ref concepts::ReferenceMap "reference map"s.
325  ///
[73]326  ///\sa concepts::Digraph
[57]327
328  class ListDigraph : public ExtendedListDigraphBase {
329  private:
[73]330    ///ListDigraph is \e not copy constructible. Use copyDigraph() instead.
[209]331
[73]332    ///ListDigraph is \e not copy constructible. Use copyDigraph() instead.
[57]333    ///
334    ListDigraph(const ListDigraph &) :ExtendedListDigraphBase() {};
335    ///\brief Assignment of ListDigraph to another one is \e not allowed.
[73]336    ///Use copyDigraph() instead.
[57]337
338    ///Assignment of ListDigraph to another one is \e not allowed.
[73]339    ///Use copyDigraph() instead.
[57]340    void operator=(const ListDigraph &) {}
341  public:
342
343    typedef ExtendedListDigraphBase Parent;
344
345    /// Constructor
[209]346
[57]347    /// Constructor.
348    ///
349    ListDigraph() {}
350
351    ///Add a new node to the digraph.
[209]352
[73]353    ///Add a new node to the digraph.
354    ///\return the new node.
[57]355    Node addNode() { return Parent::addNode(); }
356
357    ///Add a new arc to the digraph.
[209]358
[57]359    ///Add a new arc to the digraph with source node \c s
360    ///and target node \c t.
361    ///\return the new arc.
[209]362    Arc addArc(const Node& s, const Node& t) {
363      return Parent::addArc(s, t);
[57]364    }
365
[234]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
[149]378    /// Node validity check
379
380    /// This function gives back true if the given node is valid,
[209]381    /// ie. it is a real node of the graph.
[149]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,
[209]391    /// ie. it is a real arc of the graph.
[149]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
[73]398    /// Change the target of \c e to \c n
[57]399
[73]400    /// Change the target of \c e to \c n
[57]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.
[73]405    ///
[57]406    ///\warning This functionality cannot be used together with the Snapshot
407    ///feature.
[209]408    void changeTarget(Arc e, Node n) {
409      Parent::changeTarget(e,n);
[57]410    }
[73]411    /// Change the source of \c e to \c n
[57]412
[73]413    /// Change the source of \c e to \c n
[57]414    ///
415    ///\note The <tt>ArcIt</tt>s and <tt>InArcIt</tt>s referencing
416    ///the changed arc remain valid. However <tt>OutArcIt</tt>s are
417    ///invalidated.
[73]418    ///
[57]419    ///\warning This functionality cannot be used together with the Snapshot
420    ///feature.
[209]421    void changeSource(Arc e, Node n) {
[57]422      Parent::changeSource(e,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.
[73]430    ///
[57]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
[73]439    /// Reserve memory for nodes.
440
441    /// Using this function it is possible to avoid the superfluous memory
[57]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
[73]449    /// Reserve memory for arcs.
[57]450
[73]451    /// Using this function it is possible to avoid the superfluous memory
[57]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    ///
[73]467    ///\note The <tt>ArcIt</tt>s referencing a moved arc remain
[57]468    ///valid. However <tt>InArcIt</tt>s and <tt>OutArcIt</tt>s
469    ///may be invalidated.
[73]470    ///
[57]471    ///\warning This functionality cannot be used together with the Snapshot
472    ///feature.
[209]473    void contract(Node a, Node b, bool r = true)
[57]474    {
475      for(OutArcIt e(*this,b);e!=INVALID;) {
[209]476        OutArcIt f=e;
477        ++f;
478        if(r && target(e)==a) erase(e);
479        else changeSource(e,a);
480        e=f;
[57]481      }
482      for(InArcIt e(*this,b);e!=INVALID;) {
[209]483        InArcIt f=e;
484        ++f;
485        if(r && source(e)==a) erase(e);
486        else changeTarget(e,a);
487        e=f;
[57]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
[209]502    ///be invalidated.
[57]503    ///
504    ///\warning This functionality cannot be used together with the
[73]505    ///Snapshot feature.
506    ///
507    ///\todo It could be implemented in a bit faster way.
[57]508    Node split(Node n, bool connect = true) {
509      Node b = addNode();
510      for(OutArcIt e(*this,n);e!=INVALID;) {
[212]511        OutArcIt f=e;
[209]512        ++f;
513        changeSource(e,b);
514        e=f;
[57]515      }
516      if (connect) addArc(n,b);
517      return b;
518    }
[209]519
[57]520    ///Split an arc.
521
522    ///This function splits an arc. First a new node \c b is added to
523    ///the digraph, then the original arc is re-targeted to \c
524    ///b. Finally an arc from \c b to the original target is added.
[73]525    ///
526    ///\return The newly created node.
527    ///
528    ///\warning This functionality cannot be used together with the
529    ///Snapshot feature.
[57]530    Node split(Arc e) {
531      Node b = addNode();
532      addArc(b,target(e));
533      changeTarget(e,b);
534      return b;
535    }
[209]536
[57]537    /// \brief Class to make a snapshot of the digraph and restore
[73]538    /// it later.
[57]539    ///
[73]540    /// Class to make a snapshot of the digraph and restore it later.
[57]541    ///
542    /// The newly added nodes and arcs can be removed using the
543    /// restore() function.
544    ///
[73]545    /// \warning Arc and node deletions and other modifications (e.g.
[209]546    /// contracting, splitting, reversing arcs or nodes) cannot be
547    /// restored. These events invalidate the snapshot.
[57]548    class Snapshot {
549    protected:
550
551      typedef Parent::NodeNotifier NodeNotifier;
552
553      class NodeObserverProxy : public NodeNotifier::ObserverBase {
554      public:
555
556        NodeObserverProxy(Snapshot& _snapshot)
557          : snapshot(_snapshot) {}
558
559        using NodeNotifier::ObserverBase::attach;
560        using NodeNotifier::ObserverBase::detach;
561        using NodeNotifier::ObserverBase::attached;
[209]562
[57]563      protected:
[209]564
[57]565        virtual void add(const Node& node) {
566          snapshot.addNode(node);
567        }
568        virtual void add(const std::vector<Node>& nodes) {
569          for (int i = nodes.size() - 1; i >= 0; ++i) {
570            snapshot.addNode(nodes[i]);
571          }
572        }
573        virtual void erase(const Node& node) {
574          snapshot.eraseNode(node);
575        }
576        virtual void erase(const std::vector<Node>& nodes) {
577          for (int i = 0; i < int(nodes.size()); ++i) {
578            snapshot.eraseNode(nodes[i]);
579          }
580        }
581        virtual void build() {
582          Node node;
583          std::vector<Node> nodes;
[209]584          for (notifier()->first(node); node != INVALID;
[57]585               notifier()->next(node)) {
586            nodes.push_back(node);
587          }
588          for (int i = nodes.size() - 1; i >= 0; --i) {
589            snapshot.addNode(nodes[i]);
590          }
591        }
592        virtual void clear() {
593          Node node;
[209]594          for (notifier()->first(node); node != INVALID;
[57]595               notifier()->next(node)) {
596            snapshot.eraseNode(node);
597          }
598        }
599
600        Snapshot& snapshot;
601      };
602
603      class ArcObserverProxy : public ArcNotifier::ObserverBase {
604      public:
605
606        ArcObserverProxy(Snapshot& _snapshot)
607          : snapshot(_snapshot) {}
608
609        using ArcNotifier::ObserverBase::attach;
610        using ArcNotifier::ObserverBase::detach;
611        using ArcNotifier::ObserverBase::attached;
[209]612
[57]613      protected:
614
615        virtual void add(const Arc& arc) {
616          snapshot.addArc(arc);
617        }
618        virtual void add(const std::vector<Arc>& arcs) {
619          for (int i = arcs.size() - 1; i >= 0; ++i) {
620            snapshot.addArc(arcs[i]);
621          }
622        }
623        virtual void erase(const Arc& arc) {
624          snapshot.eraseArc(arc);
625        }
626        virtual void erase(const std::vector<Arc>& arcs) {
627          for (int i = 0; i < int(arcs.size()); ++i) {
628            snapshot.eraseArc(arcs[i]);
629          }
630        }
631        virtual void build() {
632          Arc arc;
633          std::vector<Arc> arcs;
[209]634          for (notifier()->first(arc); arc != INVALID;
[57]635               notifier()->next(arc)) {
636            arcs.push_back(arc);
637          }
638          for (int i = arcs.size() - 1; i >= 0; --i) {
639            snapshot.addArc(arcs[i]);
640          }
641        }
642        virtual void clear() {
643          Arc arc;
[209]644          for (notifier()->first(arc); arc != INVALID;
[57]645               notifier()->next(arc)) {
646            snapshot.eraseArc(arc);
647          }
648        }
649
650        Snapshot& snapshot;
651      };
[209]652
[57]653      ListDigraph *digraph;
654
655      NodeObserverProxy node_observer_proxy;
656      ArcObserverProxy arc_observer_proxy;
657
658      std::list<Node> added_nodes;
659      std::list<Arc> added_arcs;
660
661
662      void addNode(const Node& node) {
[209]663        added_nodes.push_front(node);
[57]664      }
665      void eraseNode(const Node& node) {
[209]666        std::list<Node>::iterator it =
[57]667          std::find(added_nodes.begin(), added_nodes.end(), node);
668        if (it == added_nodes.end()) {
669          clear();
670          arc_observer_proxy.detach();
671          throw NodeNotifier::ImmediateDetach();
672        } else {
673          added_nodes.erase(it);
674        }
675      }
676
677      void addArc(const Arc& arc) {
[209]678        added_arcs.push_front(arc);
[57]679      }
680      void eraseArc(const Arc& arc) {
[209]681        std::list<Arc>::iterator it =
[57]682          std::find(added_arcs.begin(), added_arcs.end(), arc);
683        if (it == added_arcs.end()) {
684          clear();
[209]685          node_observer_proxy.detach();
[57]686          throw ArcNotifier::ImmediateDetach();
687        } else {
688          added_arcs.erase(it);
[209]689        }
[57]690      }
691
692      void attach(ListDigraph &_digraph) {
[209]693        digraph = &_digraph;
694        node_observer_proxy.attach(digraph->notifier(Node()));
[57]695        arc_observer_proxy.attach(digraph->notifier(Arc()));
696      }
[209]697
[57]698      void detach() {
[209]699        node_observer_proxy.detach();
700        arc_observer_proxy.detach();
[57]701      }
702
703      bool attached() const {
704        return node_observer_proxy.attached();
705      }
706
707      void clear() {
708        added_nodes.clear();
[209]709        added_arcs.clear();
[57]710      }
711
712    public:
713
714      /// \brief Default constructor.
715      ///
716      /// Default constructor.
717      /// To actually make a snapshot you must call save().
[209]718      Snapshot()
719        : digraph(0), node_observer_proxy(*this),
[57]720          arc_observer_proxy(*this) {}
[209]721
[57]722      /// \brief Constructor that immediately makes a snapshot.
[209]723      ///
[57]724      /// This constructor immediately makes a snapshot of the digraph.
725      /// \param _digraph The digraph we make a snapshot of.
[209]726      Snapshot(ListDigraph &_digraph)
727        : node_observer_proxy(*this),
[57]728          arc_observer_proxy(*this) {
[209]729        attach(_digraph);
[57]730      }
[209]731
[57]732      /// \brief Make a snapshot.
733      ///
734      /// Make a snapshot of the digraph.
735      ///
736      /// This function can be called more than once. In case of a repeated
737      /// call, the previous snapshot gets lost.
738      /// \param _digraph The digraph we make the snapshot of.
739      void save(ListDigraph &_digraph) {
740        if (attached()) {
741          detach();
742          clear();
743        }
744        attach(_digraph);
745      }
[209]746
[57]747      /// \brief Undo the changes until the last snapshot.
[209]748      //
[57]749      /// Undo the changes until the last snapshot created by save().
750      void restore() {
[209]751        detach();
752        for(std::list<Arc>::iterator it = added_arcs.begin();
[57]753            it != added_arcs.end(); ++it) {
[209]754          digraph->erase(*it);
755        }
756        for(std::list<Node>::iterator it = added_nodes.begin();
[57]757            it != added_nodes.end(); ++it) {
[209]758          digraph->erase(*it);
759        }
[57]760        clear();
761      }
762
763      /// \brief Gives back true when the snapshot is valid.
764      ///
765      /// Gives back true when the snapshot is valid.
766      bool valid() const {
767        return attached();
768      }
769    };
[209]770
[57]771  };
772
773  ///@}
774
775  class ListGraphBase {
776
777  protected:
778
779    struct NodeT {
780      int first_out;
781      int prev, next;
782    };
[209]783
[57]784    struct ArcT {
785      int target;
786      int prev_out, next_out;
787    };
788
789    std::vector<NodeT> nodes;
790
791    int first_node;
792
793    int first_free_node;
794
795    std::vector<ArcT> arcs;
796
797    int first_free_arc;
[209]798
[57]799  public:
[209]800
[57]801    typedef ListGraphBase Digraph;
802
803    class Node;
804    class Arc;
805    class Edge;
[209]806
[57]807    class Node {
808      friend class ListGraphBase;
809    protected:
810
811      int id;
812      explicit Node(int pid) { id = pid;}
813
814    public:
815      Node() {}
816      Node (Invalid) { id = -1; }
817      bool operator==(const Node& node) const {return id == node.id;}
818      bool operator!=(const Node& node) const {return id != node.id;}
819      bool operator<(const Node& node) const {return id < node.id;}
820    };
821
822    class Edge {
823      friend class ListGraphBase;
824    protected:
825
826      int id;
827      explicit Edge(int pid) { id = pid;}
828
829    public:
830      Edge() {}
831      Edge (Invalid) { id = -1; }
[73]832      bool operator==(const Edge& edge) const {return id == edge.id;}
833      bool operator!=(const Edge& edge) const {return id != edge.id;}
834      bool operator<(const Edge& edge) const {return id < edge.id;}
[57]835    };
836
837    class Arc {
838      friend class ListGraphBase;
839    protected:
840
841      int id;
842      explicit Arc(int pid) { id = pid;}
843
844    public:
845      operator Edge() const { return edgeFromId(id / 2); }
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),
[209]858        first_free_node(-1), arcs(), first_free_arc(-1) {}
[57]859
[209]860
861    int maxNodeId() const { return nodes.size()-1; }
[57]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
[209]879    void first(Node& node) const {
[57]880      node.id = first_node;
881    }
882
883    void next(Node& node) const {
884      node.id = nodes[node.id].next;
885    }
886
[209]887    void first(Arc& e) const {
[57]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) {
[209]897        e.id = arcs[e.id].next_out;
[57]898      } else {
[209]899        int n = nodes[arcs[e.id ^ 1].target].next;
[57]900        while(n != -1 && nodes[n].first_out == -1) {
901          n = nodes[n].next;
902        }
[209]903        e.id = (n == -1) ? -1 : nodes[n].first_out;
904      }
[57]905    }
906
[209]907    void first(Edge& e) const {
[57]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;
[209]917        }
[57]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;
[209]932      }
[57]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;
[209]942        }
[57]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 {
[73]965      int a = nodes[v.id].first_out;
966      if (a != -1 ) {
967        e.id = a / 2;
968        d = ((a & 1) == 1);
[57]969      } else {
970        e.id = -1;
971        d = true;
972      }
973    }
974    void nextInc(Edge &e, bool& d) const {
[73]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);
[57]979      } else {
980        e.id = -1;
981        d = true;
982      }
983    }
[209]984
[57]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
[209]993    bool valid(Node n) const {
994      return n.id >= 0 && n.id < static_cast<int>(nodes.size()) &&
995        nodes[n.id].prev != -2;
[149]996    }
997
[209]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;
[149]1001    }
1002
[209]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;
[149]1006    }
1007
[209]1008    Node addNode() {
[57]1009      int n;
[209]1010
[57]1011      if(first_free_node==-1) {
[209]1012        n = nodes.size();
1013        nodes.push_back(NodeT());
[57]1014      } else {
[209]1015        n = first_free_node;
1016        first_free_node = nodes[n].next;
[57]1017      }
[209]1018
[57]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;
[209]1023
[57]1024      nodes[n].first_out = -1;
[209]1025
[57]1026      return Node(n);
1027    }
[209]1028
[57]1029    Edge addEdge(Node u, Node v) {
[209]1030      int n;
[57]1031
1032      if (first_free_arc == -1) {
[209]1033        n = arcs.size();
1034        arcs.push_back(ArcT());
1035        arcs.push_back(ArcT());
[57]1036      } else {
[209]1037        n = first_free_arc;
1038        first_free_arc = arcs[n].next_out;
[57]1039      }
[209]1040
[57]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) {
[209]1046        arcs[nodes[v.id].first_out].prev_out = n;
1047      }
[57]1048      arcs[n].prev_out = -1;
1049      nodes[v.id].first_out = n;
[209]1050
[57]1051      arcs[n | 1].next_out = nodes[u.id].first_out;
1052      if (nodes[u.id].first_out != -1) {
[209]1053        arcs[nodes[u.id].first_out].prev_out = (n | 1);
[57]1054      }
[209]1055      arcs[n | 1].prev_out = -1;
[57]1056      nodes[u.id].first_out = (n | 1);
1057
1058      return Edge(n / 2);
1059    }
[209]1060
[57]1061    void erase(const Node& node) {
1062      int n = node.id;
[209]1063
[57]1064      if(nodes[n].next != -1) {
[209]1065        nodes[nodes[n].next].prev = nodes[n].prev;
[57]1066      }
[209]1067
[57]1068      if(nodes[n].prev != -1) {
[209]1069        nodes[nodes[n].prev].next = nodes[n].next;
[57]1070      } else {
[209]1071        first_node = nodes[n].next;
[57]1072      }
[209]1073
[57]1074      nodes[n].next = first_free_node;
1075      first_free_node = n;
[149]1076      nodes[n].prev = -2;
[57]1077    }
[209]1078
[73]1079    void erase(const Edge& edge) {
1080      int n = edge.id * 2;
[209]1081
[57]1082      if (arcs[n].next_out != -1) {
[209]1083        arcs[arcs[n].next_out].prev_out = arcs[n].prev_out;
1084      }
[57]1085
1086      if (arcs[n].prev_out != -1) {
[209]1087        arcs[arcs[n].prev_out].next_out = arcs[n].next_out;
[57]1088      } else {
[209]1089        nodes[arcs[n | 1].target].first_out = arcs[n].next_out;
[57]1090      }
1091
1092      if (arcs[n | 1].next_out != -1) {
[209]1093        arcs[arcs[n | 1].next_out].prev_out = arcs[n | 1].prev_out;
1094      }
[57]1095
1096      if (arcs[n | 1].prev_out != -1) {
[209]1097        arcs[arcs[n | 1].prev_out].next_out = arcs[n | 1].next_out;
[57]1098      } else {
[209]1099        nodes[arcs[n].target].first_out = arcs[n | 1].next_out;
[57]1100      }
[209]1101
[57]1102      arcs[n].next_out = first_free_arc;
[209]1103      first_free_arc = n;
[149]1104      arcs[n].prev_out = -2;
1105      arcs[n | 1].prev_out = -2;
[57]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 changeTarget(Edge e, Node n) {
1118      if(arcs[2 * e.id].next_out != -1) {
[209]1119        arcs[arcs[2 * e.id].next_out].prev_out = arcs[2 * e.id].prev_out;
[57]1120      }
1121      if(arcs[2 * e.id].prev_out != -1) {
[209]1122        arcs[arcs[2 * e.id].prev_out].next_out =
[57]1123          arcs[2 * e.id].next_out;
1124      } else {
[209]1125        nodes[arcs[(2 * e.id) | 1].target].first_out =
[57]1126          arcs[2 * e.id].next_out;
1127      }
1128
1129      if (nodes[n.id].first_out != -1) {
[209]1130        arcs[nodes[n.id].first_out].prev_out = 2 * e.id;
[57]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 changeSource(Edge e, Node n) {
1139      if(arcs[(2 * e.id) | 1].next_out != -1) {
[209]1140        arcs[arcs[(2 * e.id) | 1].next_out].prev_out =
[57]1141          arcs[(2 * e.id) | 1].prev_out;
1142      }
1143      if(arcs[(2 * e.id) | 1].prev_out != -1) {
[209]1144        arcs[arcs[(2 * e.id) | 1].prev_out].next_out =
[57]1145          arcs[(2 * e.id) | 1].next_out;
1146      } else {
[209]1147        nodes[arcs[2 * e.id].target].first_out =
[57]1148          arcs[(2 * e.id) | 1].next_out;
1149      }
1150
1151      if (nodes[n.id].first_out != -1) {
[209]1152        arcs[nodes[n.id].first_out].prev_out = ((2 * e.id) | 1);
[57]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
[73]1165  /// \addtogroup graphs
[57]1166  /// @{
1167
[73]1168  ///A general undirected graph structure.
[57]1169
[209]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.
[57]1173  ///
[73]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
[57]1180  ///its maps are real \ref concepts::ReferenceMap "reference map"s.
1181  ///
[73]1182  ///\sa concepts::Graph
1183
[57]1184  class ListGraph : public ExtendedListGraphBase {
1185  private:
[73]1186    ///ListGraph is \e not copy constructible. Use copyGraph() instead.
[57]1187
[73]1188    ///ListGraph is \e not copy constructible. Use copyGraph() instead.
[57]1189    ///
1190    ListGraph(const ListGraph &) :ExtendedListGraphBase()  {};
1191    ///\brief Assignment of ListGraph to another one is \e not allowed.
[73]1192    ///Use copyGraph() instead.
[57]1193
1194    ///Assignment of ListGraph to another one is \e not allowed.
[73]1195    ///Use copyGraph() instead.
[57]1196    void operator=(const ListGraph &) {}
1197  public:
1198    /// Constructor
[209]1199
[57]1200    /// Constructor.
1201    ///
1202    ListGraph() {}
1203
1204    typedef ExtendedListGraphBase Parent;
1205
[73]1206    typedef Parent::OutArcIt IncEdgeIt;
[57]1207
[73]1208    /// \brief Add a new node to the graph.
[57]1209    ///
[73]1210    /// Add a new node to the graph.
[57]1211    /// \return the new node.
1212    Node addNode() { return Parent::addNode(); }
1213
[73]1214    /// \brief Add a new edge to the graph.
[57]1215    ///
[73]1216    /// Add a new edge to the graph with source node \c s
[57]1217    /// and target node \c t.
1218    /// \return the new edge.
[209]1219    Edge addEdge(const Node& s, const Node& t) {
1220      return Parent::addEdge(s, t);
[57]1221    }
[234]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); }
[149]1234    /// Node validity check
1235
1236    /// This function gives back true if the given node is valid,
[209]1237    /// ie. it is a real node of the graph.
[149]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,
[209]1246    /// ie. it is a real arc of the graph.
[149]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,
[209]1255    /// ie. it is a real arc of the graph.
[149]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); }
[73]1261    /// \brief Change the source of \c e to \c n
[57]1262    ///
[73]1263    /// This function changes the source of \c e to \c n.
[57]1264    ///
1265    ///\note The <tt>ArcIt</tt>s and <tt>InArcIt</tt>s
1266    ///referencing the changed arc remain
1267    ///valid. However <tt>OutArcIt</tt>s are invalidated.
[73]1268    ///
1269    ///\warning This functionality cannot be used together with the
1270    ///Snapshot feature.
[209]1271    void changeSource(Edge e, Node n) {
1272      Parent::changeSource(e,n);
1273    }
[73]1274    /// \brief Change the target of \c e to \c n
[57]1275    ///
[73]1276    /// This function changes the target of \c e to \c n.
[57]1277    ///
1278    /// \note The <tt>ArcIt</tt>s referencing the changed arc remain
1279    /// valid. However the other iterators may be invalidated.
[73]1280    ///
1281    ///\warning This functionality cannot be used together with the
1282    ///Snapshot feature.
[209]1283    void changeTarget(Edge e, Node n) {
1284      Parent::changeTarget(e,n);
[57]1285    }
[73]1286    /// \brief Change the source of \c e to \c n
[57]1287    ///
[209]1288    /// This function changes the source of \c e to \c n.
[73]1289    /// It also changes the proper node of the represented edge.
[57]1290    ///
1291    ///\note The <tt>ArcIt</tt>s and <tt>InArcIt</tt>s
1292    ///referencing the changed arc remain
1293    ///valid. However <tt>OutArcIt</tt>s are invalidated.
[73]1294    ///
1295    ///\warning This functionality cannot be used together with the
1296    ///Snapshot feature.
[209]1297    void changeSource(Arc e, Node n) {
[57]1298      if (Parent::direction(e)) {
1299        Parent::changeSource(e,n);
1300      } else {
1301        Parent::changeTarget(e,n);
[209]1302      }
[57]1303    }
[73]1304    /// \brief Change the target of \c e to \c n
[57]1305    ///
[209]1306    /// This function changes the target of \c e to \c n.
[73]1307    /// It also changes the proper node of the represented edge.
[57]1308    ///
1309    ///\note The <tt>ArcIt</tt>s and <tt>OutArcIt</tt>s
1310    ///referencing the changed arc remain
1311    ///valid. However <tt>InArcIt</tt>s are invalidated.
[73]1312    ///
1313    ///\warning This functionality cannot be used together with the
1314    ///Snapshot feature.
[209]1315    void changeTarget(Arc e, Node n) {
[57]1316      if (Parent::direction(e)) {
1317        Parent::changeTarget(e,n);
1318      } else {
1319        Parent::changeSource(e,n);
[209]1320      }
[57]1321    }
1322    /// \brief Contract two nodes.
1323    ///
1324    /// This function contracts two nodes.
1325    /// Node \p b will be removed but instead of deleting
1326    /// its neighboring arcs, they will be joined to \p a.
1327    /// The last parameter \p r controls whether to remove loops. \c true
1328    /// means that loops will be removed.
1329    ///
1330    /// \note The <tt>ArcIt</tt>s referencing a moved arc remain
1331    /// valid.
[73]1332    ///
1333    ///\warning This functionality cannot be used together with the
1334    ///Snapshot feature.
[57]1335    void contract(Node a, Node b, bool r = true) {
[73]1336      for(IncEdgeIt e(*this, b); e!=INVALID;) {
[209]1337        IncEdgeIt f = e; ++f;
1338        if (r && runningNode(e) == a) {
1339          erase(e);
1340        } else if (source(e) == b) {
1341          changeSource(e, a);
1342        } else {
1343          changeTarget(e, a);
1344        }
1345        e = f;
[57]1346      }
1347      erase(b);
1348    }
1349
1350
[73]1351    /// \brief Class to make a snapshot of the graph and restore
1352    /// it later.
[57]1353    ///
[73]1354    /// Class to make a snapshot of the graph and restore it later.
[57]1355    ///
1356    /// The newly added nodes and edges can be removed
1357    /// using the restore() function.
1358    ///
[73]1359    /// \warning Edge and node deletions and other modifications
[209]1360    /// (e.g. changing nodes of edges, contracting nodes) cannot be
[73]1361    /// restored. These events invalidate the snapshot.
[57]1362    class Snapshot {
1363    protected:
1364
1365      typedef Parent::NodeNotifier NodeNotifier;
1366
1367      class NodeObserverProxy : public NodeNotifier::ObserverBase {
1368      public:
1369
1370        NodeObserverProxy(Snapshot& _snapshot)
1371          : snapshot(_snapshot) {}
1372
1373        using NodeNotifier::ObserverBase::attach;
1374        using NodeNotifier::ObserverBase::detach;
1375        using NodeNotifier::ObserverBase::attached;
[209]1376
[57]1377      protected:
[209]1378
[57]1379        virtual void add(const Node& node) {
1380          snapshot.addNode(node);
1381        }
1382        virtual void add(const std::vector<Node>& nodes) {
1383          for (int i = nodes.size() - 1; i >= 0; ++i) {
1384            snapshot.addNode(nodes[i]);
1385          }
1386        }
1387        virtual void erase(const Node& node) {
1388          snapshot.eraseNode(node);
1389        }
1390        virtual void erase(const std::vector<Node>& nodes) {
1391          for (int i = 0; i < int(nodes.size()); ++i) {
1392            snapshot.eraseNode(nodes[i]);
1393          }
1394        }
1395        virtual void build() {
1396          Node node;
1397          std::vector<Node> nodes;
[209]1398          for (notifier()->first(node); node != INVALID;
[57]1399               notifier()->next(node)) {
1400            nodes.push_back(node);
1401          }
1402          for (int i = nodes.size() - 1; i >= 0; --i) {
1403            snapshot.addNode(nodes[i]);
1404          }
1405        }
1406        virtual void clear() {
1407          Node node;
[209]1408          for (notifier()->first(node); node != INVALID;
[57]1409               notifier()->next(node)) {
1410            snapshot.eraseNode(node);
1411          }
1412        }
1413
1414        Snapshot& snapshot;
1415      };
1416
1417      class EdgeObserverProxy : public EdgeNotifier::ObserverBase {
1418      public:
1419
1420        EdgeObserverProxy(Snapshot& _snapshot)
1421          : snapshot(_snapshot) {}
1422
1423        using EdgeNotifier::ObserverBase::attach;
1424        using EdgeNotifier::ObserverBase::detach;
1425        using EdgeNotifier::ObserverBase::attached;
[209]1426
[57]1427      protected:
1428
[73]1429        virtual void add(const Edge& edge) {
1430          snapshot.addEdge(edge);
[57]1431        }
[73]1432        virtual void add(const std::vector<Edge>& edges) {
1433          for (int i = edges.size() - 1; i >= 0; ++i) {
1434            snapshot.addEdge(edges[i]);
[57]1435          }
1436        }
[73]1437        virtual void erase(const Edge& edge) {
1438          snapshot.eraseEdge(edge);
[57]1439        }
[73]1440        virtual void erase(const std::vector<Edge>& edges) {
1441          for (int i = 0; i < int(edges.size()); ++i) {
1442            snapshot.eraseEdge(edges[i]);
[57]1443          }
1444        }
1445        virtual void build() {
[73]1446          Edge edge;
1447          std::vector<Edge> edges;
[209]1448          for (notifier()->first(edge); edge != INVALID;
[73]1449               notifier()->next(edge)) {
1450            edges.push_back(edge);
[57]1451          }
[73]1452          for (int i = edges.size() - 1; i >= 0; --i) {
1453            snapshot.addEdge(edges[i]);
[57]1454          }
1455        }
1456        virtual void clear() {
[73]1457          Edge edge;
[209]1458          for (notifier()->first(edge); edge != INVALID;
[73]1459               notifier()->next(edge)) {
1460            snapshot.eraseEdge(edge);
[57]1461          }
1462        }
1463
1464        Snapshot& snapshot;
1465      };
[73]1466
1467      ListGraph *graph;
[57]1468
1469      NodeObserverProxy node_observer_proxy;
[73]1470      EdgeObserverProxy edge_observer_proxy;
[57]1471
1472      std::list<Node> added_nodes;
[73]1473      std::list<Edge> added_edges;
[57]1474
1475
1476      void addNode(const Node& node) {
[209]1477        added_nodes.push_front(node);
[57]1478      }
1479      void eraseNode(const Node& node) {
[209]1480        std::list<Node>::iterator it =
[57]1481          std::find(added_nodes.begin(), added_nodes.end(), node);
1482        if (it == added_nodes.end()) {
1483          clear();
[73]1484          edge_observer_proxy.detach();
[57]1485          throw NodeNotifier::ImmediateDetach();
1486        } else {
1487          added_nodes.erase(it);
1488        }
1489      }
1490
[73]1491      void addEdge(const Edge& edge) {
[209]1492        added_edges.push_front(edge);
[57]1493      }
[73]1494      void eraseEdge(const Edge& edge) {
[209]1495        std::list<Edge>::iterator it =
[73]1496          std::find(added_edges.begin(), added_edges.end(), edge);
1497        if (it == added_edges.end()) {
[57]1498          clear();
1499          node_observer_proxy.detach();
1500          throw EdgeNotifier::ImmediateDetach();
1501        } else {
[73]1502          added_edges.erase(it);
1503        }
[57]1504      }
1505
[73]1506      void attach(ListGraph &_graph) {
[209]1507        graph = &_graph;
1508        node_observer_proxy.attach(graph->notifier(Node()));
[73]1509        edge_observer_proxy.attach(graph->notifier(Edge()));
[57]1510      }
[209]1511
[57]1512      void detach() {
[209]1513        node_observer_proxy.detach();
1514        edge_observer_proxy.detach();
[57]1515      }
1516
1517      bool attached() const {
1518        return node_observer_proxy.attached();
1519      }
1520
1521      void clear() {
1522        added_nodes.clear();
[209]1523        added_edges.clear();
[57]1524      }
1525
1526    public:
1527
1528      /// \brief Default constructor.
1529      ///
1530      /// Default constructor.
1531      /// To actually make a snapshot you must call save().
[209]1532      Snapshot()
1533        : graph(0), node_observer_proxy(*this),
[73]1534          edge_observer_proxy(*this) {}
[209]1535
[57]1536      /// \brief Constructor that immediately makes a snapshot.
[209]1537      ///
[73]1538      /// This constructor immediately makes a snapshot of the graph.
1539      /// \param _graph The graph we make a snapshot of.
[209]1540      Snapshot(ListGraph &_graph)
1541        : node_observer_proxy(*this),
[73]1542          edge_observer_proxy(*this) {
[209]1543        attach(_graph);
[57]1544      }
[209]1545
[57]1546      /// \brief Make a snapshot.
1547      ///
[73]1548      /// Make a snapshot of the graph.
[57]1549      ///
1550      /// This function can be called more than once. In case of a repeated
1551      /// call, the previous snapshot gets lost.
[73]1552      /// \param _graph The graph we make the snapshot of.
1553      void save(ListGraph &_graph) {
[57]1554        if (attached()) {
1555          detach();
1556          clear();
1557        }
[73]1558        attach(_graph);
[57]1559      }
[209]1560
[57]1561      /// \brief Undo the changes until the last snapshot.
[209]1562      //
[57]1563      /// Undo the changes until the last snapshot created by save().
1564      void restore() {
[209]1565        detach();
1566        for(std::list<Edge>::iterator it = added_edges.begin();
[73]1567            it != added_edges.end(); ++it) {
[209]1568          graph->erase(*it);
1569        }
1570        for(std::list<Node>::iterator it = added_nodes.begin();
[57]1571            it != added_nodes.end(); ++it) {
[209]1572          graph->erase(*it);
1573        }
[57]1574        clear();
1575      }
1576
1577      /// \brief Gives back true when the snapshot is valid.
1578      ///
1579      /// Gives back true when the snapshot is valid.
1580      bool valid() const {
1581        return attached();
1582      }
1583    };
1584  };
[209]1585
1586  /// @}
[57]1587} //namespace lemon
[209]1588
[57]1589
1590#endif
Note: See TracBrowser for help on using the repository browser.