lemon/smart_graph.h
author Alpar Juttner <alpar@cs.elte.hu>
Sun, 27 Sep 2009 09:47:20 +0200
changeset 748 4792459983d0
parent 582 7a28e215f715
child 735 853fcddcf282
child 778 a143f19f465b
permissions -rw-r--r--
Fix (and improve) error message in mip_test.cc (#317)
     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_SMART_GRAPH_H
    20 #define LEMON_SMART_GRAPH_H
    21 
    22 ///\ingroup graphs
    23 ///\file
    24 ///\brief SmartDigraph and SmartGraph classes.
    25 
    26 #include <vector>
    27 
    28 #include <lemon/core.h>
    29 #include <lemon/error.h>
    30 #include <lemon/bits/graph_extender.h>
    31 
    32 namespace lemon {
    33 
    34   class SmartDigraph;
    35   ///Base of SmartDigraph
    36 
    37   ///Base of SmartDigraph
    38   ///
    39   class SmartDigraphBase {
    40   protected:
    41 
    42     struct NodeT
    43     {
    44       int first_in, first_out;
    45       NodeT() {}
    46     };
    47     struct ArcT
    48     {
    49       int target, source, next_in, next_out;
    50       ArcT() {}
    51     };
    52 
    53     std::vector<NodeT> nodes;
    54     std::vector<ArcT> arcs;
    55 
    56   public:
    57 
    58     typedef SmartDigraphBase Digraph;
    59 
    60     class Node;
    61     class Arc;
    62 
    63   public:
    64 
    65     SmartDigraphBase() : nodes(), arcs() { }
    66     SmartDigraphBase(const SmartDigraphBase &_g)
    67       : nodes(_g.nodes), arcs(_g.arcs) { }
    68 
    69     typedef True NodeNumTag;
    70     typedef True ArcNumTag;
    71 
    72     int nodeNum() const { return nodes.size(); }
    73     int arcNum() const { return arcs.size(); }
    74 
    75     int maxNodeId() const { return nodes.size()-1; }
    76     int maxArcId() const { return arcs.size()-1; }
    77 
    78     Node addNode() {
    79       int n = nodes.size();
    80       nodes.push_back(NodeT());
    81       nodes[n].first_in = -1;
    82       nodes[n].first_out = -1;
    83       return Node(n);
    84     }
    85 
    86     Arc addArc(Node u, Node v) {
    87       int n = arcs.size();
    88       arcs.push_back(ArcT());
    89       arcs[n].source = u._id;
    90       arcs[n].target = v._id;
    91       arcs[n].next_out = nodes[u._id].first_out;
    92       arcs[n].next_in = nodes[v._id].first_in;
    93       nodes[u._id].first_out = nodes[v._id].first_in = n;
    94 
    95       return Arc(n);
    96     }
    97 
    98     void clear() {
    99       arcs.clear();
   100       nodes.clear();
   101     }
   102 
   103     Node source(Arc a) const { return Node(arcs[a._id].source); }
   104     Node target(Arc a) const { return Node(arcs[a._id].target); }
   105 
   106     static int id(Node v) { return v._id; }
   107     static int id(Arc a) { return a._id; }
   108 
   109     static Node nodeFromId(int id) { return Node(id);}
   110     static Arc arcFromId(int id) { return Arc(id);}
   111 
   112     bool valid(Node n) const {
   113       return n._id >= 0 && n._id < static_cast<int>(nodes.size());
   114     }
   115     bool valid(Arc a) const {
   116       return a._id >= 0 && a._id < static_cast<int>(arcs.size());
   117     }
   118 
   119     class Node {
   120       friend class SmartDigraphBase;
   121       friend class SmartDigraph;
   122 
   123     protected:
   124       int _id;
   125       explicit Node(int id) : _id(id) {}
   126     public:
   127       Node() {}
   128       Node (Invalid) : _id(-1) {}
   129       bool operator==(const Node i) const {return _id == i._id;}
   130       bool operator!=(const Node i) const {return _id != i._id;}
   131       bool operator<(const Node i) const {return _id < i._id;}
   132     };
   133 
   134 
   135     class Arc {
   136       friend class SmartDigraphBase;
   137       friend class SmartDigraph;
   138 
   139     protected:
   140       int _id;
   141       explicit Arc(int id) : _id(id) {}
   142     public:
   143       Arc() { }
   144       Arc (Invalid) : _id(-1) {}
   145       bool operator==(const Arc i) const {return _id == i._id;}
   146       bool operator!=(const Arc i) const {return _id != i._id;}
   147       bool operator<(const Arc i) const {return _id < i._id;}
   148     };
   149 
   150     void first(Node& node) const {
   151       node._id = nodes.size() - 1;
   152     }
   153 
   154     static void next(Node& node) {
   155       --node._id;
   156     }
   157 
   158     void first(Arc& arc) const {
   159       arc._id = arcs.size() - 1;
   160     }
   161 
   162     static void next(Arc& arc) {
   163       --arc._id;
   164     }
   165 
   166     void firstOut(Arc& arc, const Node& node) const {
   167       arc._id = nodes[node._id].first_out;
   168     }
   169 
   170     void nextOut(Arc& arc) const {
   171       arc._id = arcs[arc._id].next_out;
   172     }
   173 
   174     void firstIn(Arc& arc, const Node& node) const {
   175       arc._id = nodes[node._id].first_in;
   176     }
   177 
   178     void nextIn(Arc& arc) const {
   179       arc._id = arcs[arc._id].next_in;
   180     }
   181 
   182   };
   183 
   184   typedef DigraphExtender<SmartDigraphBase> ExtendedSmartDigraphBase;
   185 
   186   ///\ingroup graphs
   187   ///
   188   ///\brief A smart directed graph class.
   189   ///
   190   ///This is a simple and fast digraph implementation.
   191   ///It is also quite memory efficient, but at the price
   192   ///that <b> it does support only limited (only stack-like)
   193   ///node and arc deletions</b>.
   194   ///It fully conforms to the \ref concepts::Digraph "Digraph concept".
   195   ///
   196   ///\sa concepts::Digraph.
   197   class SmartDigraph : public ExtendedSmartDigraphBase {
   198     typedef ExtendedSmartDigraphBase Parent;
   199 
   200   private:
   201 
   202     ///SmartDigraph is \e not copy constructible. Use DigraphCopy() instead.
   203 
   204     ///SmartDigraph is \e not copy constructible. Use DigraphCopy() instead.
   205     ///
   206     SmartDigraph(const SmartDigraph &) : ExtendedSmartDigraphBase() {};
   207     ///\brief Assignment of SmartDigraph to another one is \e not allowed.
   208     ///Use DigraphCopy() instead.
   209 
   210     ///Assignment of SmartDigraph to another one is \e not allowed.
   211     ///Use DigraphCopy() instead.
   212     void operator=(const SmartDigraph &) {}
   213 
   214   public:
   215 
   216     /// Constructor
   217 
   218     /// Constructor.
   219     ///
   220     SmartDigraph() {};
   221 
   222     ///Add a new node to the digraph.
   223 
   224     /// Add a new node to the digraph.
   225     /// \return The new node.
   226     Node addNode() { return Parent::addNode(); }
   227 
   228     ///Add a new arc to the digraph.
   229 
   230     ///Add a new arc to the digraph with source node \c s
   231     ///and target node \c t.
   232     ///\return The new arc.
   233     Arc addArc(const Node& s, const Node& t) {
   234       return Parent::addArc(s, t);
   235     }
   236 
   237     /// \brief Using this it is possible to avoid the superfluous memory
   238     /// allocation.
   239 
   240     /// Using this it is possible to avoid the superfluous memory
   241     /// allocation: if you know that the digraph you want to build will
   242     /// be very large (e.g. it will contain millions of nodes and/or arcs)
   243     /// then it is worth reserving space for this amount before starting
   244     /// to build the digraph.
   245     /// \sa reserveArc
   246     void reserveNode(int n) { nodes.reserve(n); };
   247 
   248     /// \brief Using this it is possible to avoid the superfluous memory
   249     /// allocation.
   250 
   251     /// Using this it is possible to avoid the superfluous memory
   252     /// allocation: if you know that the digraph you want to build will
   253     /// be very large (e.g. it will contain millions of nodes and/or arcs)
   254     /// then it is worth reserving space for this amount before starting
   255     /// to build the digraph.
   256     /// \sa reserveNode
   257     void reserveArc(int m) { arcs.reserve(m); };
   258 
   259     /// \brief Node validity check
   260     ///
   261     /// This function gives back true if the given node is valid,
   262     /// ie. it is a real node of the graph.
   263     ///
   264     /// \warning A removed node (using Snapshot) could become valid again
   265     /// when new nodes are added to the graph.
   266     bool valid(Node n) const { return Parent::valid(n); }
   267 
   268     /// \brief Arc validity check
   269     ///
   270     /// This function gives back true if the given arc is valid,
   271     /// ie. it is a real arc of the graph.
   272     ///
   273     /// \warning A removed arc (using Snapshot) could become valid again
   274     /// when new arcs are added to the graph.
   275     bool valid(Arc a) const { return Parent::valid(a); }
   276 
   277     ///Clear the digraph.
   278 
   279     ///Erase all the nodes and arcs from the digraph.
   280     ///
   281     void clear() {
   282       Parent::clear();
   283     }
   284 
   285     ///Split a node.
   286 
   287     ///This function splits a node. First a new node is added to the digraph,
   288     ///then the source of each outgoing arc of \c n is moved to this new node.
   289     ///If \c connect is \c true (this is the default value), then a new arc
   290     ///from \c n to the newly created node is also added.
   291     ///\return The newly created node.
   292     ///
   293     ///\note The <tt>Arc</tt>s
   294     ///referencing a moved arc remain
   295     ///valid. However <tt>InArc</tt>'s and <tt>OutArc</tt>'s
   296     ///may be invalidated.
   297     ///\warning This functionality cannot be used together with the Snapshot
   298     ///feature.
   299     Node split(Node n, bool connect = true)
   300     {
   301       Node b = addNode();
   302       nodes[b._id].first_out=nodes[n._id].first_out;
   303       nodes[n._id].first_out=-1;
   304       for(int i=nodes[b._id].first_out; i!=-1; i=arcs[i].next_out) {
   305         arcs[i].source=b._id;
   306       }
   307       if(connect) addArc(n,b);
   308       return b;
   309     }
   310 
   311   public:
   312 
   313     class Snapshot;
   314 
   315   protected:
   316 
   317     void restoreSnapshot(const Snapshot &s)
   318     {
   319       while(s.arc_num<arcs.size()) {
   320         Arc arc = arcFromId(arcs.size()-1);
   321         Parent::notifier(Arc()).erase(arc);
   322         nodes[arcs.back().source].first_out=arcs.back().next_out;
   323         nodes[arcs.back().target].first_in=arcs.back().next_in;
   324         arcs.pop_back();
   325       }
   326       while(s.node_num<nodes.size()) {
   327         Node node = nodeFromId(nodes.size()-1);
   328         Parent::notifier(Node()).erase(node);
   329         nodes.pop_back();
   330       }
   331     }
   332 
   333   public:
   334 
   335     ///Class to make a snapshot of the digraph and to restrore to it later.
   336 
   337     ///Class to make a snapshot of the digraph and to restrore to it later.
   338     ///
   339     ///The newly added nodes and arcs can be removed using the
   340     ///restore() function.
   341     ///\note After you restore a state, you cannot restore
   342     ///a later state, in other word you cannot add again the arcs deleted
   343     ///by restore() using another one Snapshot instance.
   344     ///
   345     ///\warning If you do not use correctly the snapshot that can cause
   346     ///either broken program, invalid state of the digraph, valid but
   347     ///not the restored digraph or no change. Because the runtime performance
   348     ///the validity of the snapshot is not stored.
   349     class Snapshot
   350     {
   351       SmartDigraph *_graph;
   352     protected:
   353       friend class SmartDigraph;
   354       unsigned int node_num;
   355       unsigned int arc_num;
   356     public:
   357       ///Default constructor.
   358 
   359       ///Default constructor.
   360       ///To actually make a snapshot you must call save().
   361       ///
   362       Snapshot() : _graph(0) {}
   363       ///Constructor that immediately makes a snapshot
   364 
   365       ///This constructor immediately makes a snapshot of the digraph.
   366       ///\param graph The digraph we make a snapshot of.
   367       Snapshot(SmartDigraph &graph) : _graph(&graph) {
   368         node_num=_graph->nodes.size();
   369         arc_num=_graph->arcs.size();
   370       }
   371 
   372       ///Make a snapshot.
   373 
   374       ///Make a snapshot of the digraph.
   375       ///
   376       ///This function can be called more than once. In case of a repeated
   377       ///call, the previous snapshot gets lost.
   378       ///\param graph The digraph we make the snapshot of.
   379       void save(SmartDigraph &graph)
   380       {
   381         _graph=&graph;
   382         node_num=_graph->nodes.size();
   383         arc_num=_graph->arcs.size();
   384       }
   385 
   386       ///Undo the changes until a snapshot.
   387 
   388       ///Undo the changes until a snapshot created by save().
   389       ///
   390       ///\note After you restored a state, you cannot restore
   391       ///a later state, in other word you cannot add again the arcs deleted
   392       ///by restore().
   393       void restore()
   394       {
   395         _graph->restoreSnapshot(*this);
   396       }
   397     };
   398   };
   399 
   400 
   401   class SmartGraphBase {
   402 
   403   protected:
   404 
   405     struct NodeT {
   406       int first_out;
   407     };
   408 
   409     struct ArcT {
   410       int target;
   411       int next_out;
   412     };
   413 
   414     std::vector<NodeT> nodes;
   415     std::vector<ArcT> arcs;
   416 
   417     int first_free_arc;
   418 
   419   public:
   420 
   421     typedef SmartGraphBase Graph;
   422 
   423     class Node;
   424     class Arc;
   425     class Edge;
   426 
   427     class Node {
   428       friend class SmartGraphBase;
   429     protected:
   430 
   431       int _id;
   432       explicit Node(int id) { _id = id;}
   433 
   434     public:
   435       Node() {}
   436       Node (Invalid) { _id = -1; }
   437       bool operator==(const Node& node) const {return _id == node._id;}
   438       bool operator!=(const Node& node) const {return _id != node._id;}
   439       bool operator<(const Node& node) const {return _id < node._id;}
   440     };
   441 
   442     class Edge {
   443       friend class SmartGraphBase;
   444     protected:
   445 
   446       int _id;
   447       explicit Edge(int id) { _id = id;}
   448 
   449     public:
   450       Edge() {}
   451       Edge (Invalid) { _id = -1; }
   452       bool operator==(const Edge& arc) const {return _id == arc._id;}
   453       bool operator!=(const Edge& arc) const {return _id != arc._id;}
   454       bool operator<(const Edge& arc) const {return _id < arc._id;}
   455     };
   456 
   457     class Arc {
   458       friend class SmartGraphBase;
   459     protected:
   460 
   461       int _id;
   462       explicit Arc(int id) { _id = id;}
   463 
   464     public:
   465       operator Edge() const {
   466         return _id != -1 ? edgeFromId(_id / 2) : INVALID;
   467       }
   468 
   469       Arc() {}
   470       Arc (Invalid) { _id = -1; }
   471       bool operator==(const Arc& arc) const {return _id == arc._id;}
   472       bool operator!=(const Arc& arc) const {return _id != arc._id;}
   473       bool operator<(const Arc& arc) const {return _id < arc._id;}
   474     };
   475 
   476 
   477 
   478     SmartGraphBase()
   479       : nodes(), arcs() {}
   480 
   481     typedef True NodeNumTag;
   482     typedef True EdgeNumTag;
   483     typedef True ArcNumTag;
   484 
   485     int nodeNum() const { return nodes.size(); }
   486     int edgeNum() const { return arcs.size() / 2; }
   487     int arcNum() const { return arcs.size(); }
   488 
   489     int maxNodeId() const { return nodes.size()-1; }
   490     int maxEdgeId() const { return arcs.size() / 2 - 1; }
   491     int maxArcId() const { return arcs.size()-1; }
   492 
   493     Node source(Arc e) const { return Node(arcs[e._id ^ 1].target); }
   494     Node target(Arc e) const { return Node(arcs[e._id].target); }
   495 
   496     Node u(Edge e) const { return Node(arcs[2 * e._id].target); }
   497     Node v(Edge e) const { return Node(arcs[2 * e._id + 1].target); }
   498 
   499     static bool direction(Arc e) {
   500       return (e._id & 1) == 1;
   501     }
   502 
   503     static Arc direct(Edge e, bool d) {
   504       return Arc(e._id * 2 + (d ? 1 : 0));
   505     }
   506 
   507     void first(Node& node) const {
   508       node._id = nodes.size() - 1;
   509     }
   510 
   511     void next(Node& node) const {
   512       --node._id;
   513     }
   514 
   515     void first(Arc& arc) const {
   516       arc._id = arcs.size() - 1;
   517     }
   518 
   519     void next(Arc& arc) const {
   520       --arc._id;
   521     }
   522 
   523     void first(Edge& arc) const {
   524       arc._id = arcs.size() / 2 - 1;
   525     }
   526 
   527     void next(Edge& arc) const {
   528       --arc._id;
   529     }
   530 
   531     void firstOut(Arc &arc, const Node& v) const {
   532       arc._id = nodes[v._id].first_out;
   533     }
   534     void nextOut(Arc &arc) const {
   535       arc._id = arcs[arc._id].next_out;
   536     }
   537 
   538     void firstIn(Arc &arc, const Node& v) const {
   539       arc._id = ((nodes[v._id].first_out) ^ 1);
   540       if (arc._id == -2) arc._id = -1;
   541     }
   542     void nextIn(Arc &arc) const {
   543       arc._id = ((arcs[arc._id ^ 1].next_out) ^ 1);
   544       if (arc._id == -2) arc._id = -1;
   545     }
   546 
   547     void firstInc(Edge &arc, bool& d, const Node& v) const {
   548       int de = nodes[v._id].first_out;
   549       if (de != -1) {
   550         arc._id = de / 2;
   551         d = ((de & 1) == 1);
   552       } else {
   553         arc._id = -1;
   554         d = true;
   555       }
   556     }
   557     void nextInc(Edge &arc, bool& d) const {
   558       int de = (arcs[(arc._id * 2) | (d ? 1 : 0)].next_out);
   559       if (de != -1) {
   560         arc._id = de / 2;
   561         d = ((de & 1) == 1);
   562       } else {
   563         arc._id = -1;
   564         d = true;
   565       }
   566     }
   567 
   568     static int id(Node v) { return v._id; }
   569     static int id(Arc e) { return e._id; }
   570     static int id(Edge e) { return e._id; }
   571 
   572     static Node nodeFromId(int id) { return Node(id);}
   573     static Arc arcFromId(int id) { return Arc(id);}
   574     static Edge edgeFromId(int id) { return Edge(id);}
   575 
   576     bool valid(Node n) const {
   577       return n._id >= 0 && n._id < static_cast<int>(nodes.size());
   578     }
   579     bool valid(Arc a) const {
   580       return a._id >= 0 && a._id < static_cast<int>(arcs.size());
   581     }
   582     bool valid(Edge e) const {
   583       return e._id >= 0 && 2 * e._id < static_cast<int>(arcs.size());
   584     }
   585 
   586     Node addNode() {
   587       int n = nodes.size();
   588       nodes.push_back(NodeT());
   589       nodes[n].first_out = -1;
   590 
   591       return Node(n);
   592     }
   593 
   594     Edge addEdge(Node u, Node v) {
   595       int n = arcs.size();
   596       arcs.push_back(ArcT());
   597       arcs.push_back(ArcT());
   598 
   599       arcs[n].target = u._id;
   600       arcs[n | 1].target = v._id;
   601 
   602       arcs[n].next_out = nodes[v._id].first_out;
   603       nodes[v._id].first_out = n;
   604 
   605       arcs[n | 1].next_out = nodes[u._id].first_out;
   606       nodes[u._id].first_out = (n | 1);
   607 
   608       return Edge(n / 2);
   609     }
   610 
   611     void clear() {
   612       arcs.clear();
   613       nodes.clear();
   614     }
   615 
   616   };
   617 
   618   typedef GraphExtender<SmartGraphBase> ExtendedSmartGraphBase;
   619 
   620   /// \ingroup graphs
   621   ///
   622   /// \brief A smart undirected graph class.
   623   ///
   624   /// This is a simple and fast graph implementation.
   625   /// It is also quite memory efficient, but at the price
   626   /// that <b> it does support only limited (only stack-like)
   627   /// node and arc deletions</b>.
   628   /// It fully conforms to the \ref concepts::Graph "Graph concept".
   629   ///
   630   /// \sa concepts::Graph.
   631   class SmartGraph : public ExtendedSmartGraphBase {
   632     typedef ExtendedSmartGraphBase Parent;
   633 
   634   private:
   635 
   636     ///SmartGraph is \e not copy constructible. Use GraphCopy() instead.
   637 
   638     ///SmartGraph is \e not copy constructible. Use GraphCopy() instead.
   639     ///
   640     SmartGraph(const SmartGraph &) : ExtendedSmartGraphBase() {};
   641 
   642     ///\brief Assignment of SmartGraph to another one is \e not allowed.
   643     ///Use GraphCopy() instead.
   644 
   645     ///Assignment of SmartGraph to another one is \e not allowed.
   646     ///Use GraphCopy() instead.
   647     void operator=(const SmartGraph &) {}
   648 
   649   public:
   650 
   651     /// Constructor
   652 
   653     /// Constructor.
   654     ///
   655     SmartGraph() {}
   656 
   657     ///Add a new node to the graph.
   658 
   659     /// Add a new node to the graph.
   660     /// \return The new node.
   661     Node addNode() { return Parent::addNode(); }
   662 
   663     ///Add a new edge to the graph.
   664 
   665     ///Add a new edge to the graph with node \c s
   666     ///and \c t.
   667     ///\return The new edge.
   668     Edge addEdge(const Node& s, const Node& t) {
   669       return Parent::addEdge(s, t);
   670     }
   671 
   672     /// \brief Node validity check
   673     ///
   674     /// This function gives back true if the given node is valid,
   675     /// ie. it is a real node of the graph.
   676     ///
   677     /// \warning A removed node (using Snapshot) could become valid again
   678     /// when new nodes are added to the graph.
   679     bool valid(Node n) const { return Parent::valid(n); }
   680 
   681     /// \brief Arc validity check
   682     ///
   683     /// This function gives back true if the given arc is valid,
   684     /// ie. it is a real arc of the graph.
   685     ///
   686     /// \warning A removed arc (using Snapshot) could become valid again
   687     /// when new edges are added to the graph.
   688     bool valid(Arc a) const { return Parent::valid(a); }
   689 
   690     /// \brief Edge validity check
   691     ///
   692     /// This function gives back true if the given edge is valid,
   693     /// ie. it is a real edge of the graph.
   694     ///
   695     /// \warning A removed edge (using Snapshot) could become valid again
   696     /// when new edges are added to the graph.
   697     bool valid(Edge e) const { return Parent::valid(e); }
   698 
   699     ///Clear the graph.
   700 
   701     ///Erase all the nodes and edges from the graph.
   702     ///
   703     void clear() {
   704       Parent::clear();
   705     }
   706 
   707   public:
   708 
   709     class Snapshot;
   710 
   711   protected:
   712 
   713     void saveSnapshot(Snapshot &s)
   714     {
   715       s._graph = this;
   716       s.node_num = nodes.size();
   717       s.arc_num = arcs.size();
   718     }
   719 
   720     void restoreSnapshot(const Snapshot &s)
   721     {
   722       while(s.arc_num<arcs.size()) {
   723         int n=arcs.size()-1;
   724         Edge arc=edgeFromId(n/2);
   725         Parent::notifier(Edge()).erase(arc);
   726         std::vector<Arc> dir;
   727         dir.push_back(arcFromId(n));
   728         dir.push_back(arcFromId(n-1));
   729         Parent::notifier(Arc()).erase(dir);
   730         nodes[arcs[n-1].target].first_out=arcs[n].next_out;
   731         nodes[arcs[n].target].first_out=arcs[n-1].next_out;
   732         arcs.pop_back();
   733         arcs.pop_back();
   734       }
   735       while(s.node_num<nodes.size()) {
   736         int n=nodes.size()-1;
   737         Node node = nodeFromId(n);
   738         Parent::notifier(Node()).erase(node);
   739         nodes.pop_back();
   740       }
   741     }
   742 
   743   public:
   744 
   745     ///Class to make a snapshot of the digraph and to restrore to it later.
   746 
   747     ///Class to make a snapshot of the digraph and to restrore to it later.
   748     ///
   749     ///The newly added nodes and arcs can be removed using the
   750     ///restore() function.
   751     ///
   752     ///\note After you restore a state, you cannot restore
   753     ///a later state, in other word you cannot add again the arcs deleted
   754     ///by restore() using another one Snapshot instance.
   755     ///
   756     ///\warning If you do not use correctly the snapshot that can cause
   757     ///either broken program, invalid state of the digraph, valid but
   758     ///not the restored digraph or no change. Because the runtime performance
   759     ///the validity of the snapshot is not stored.
   760     class Snapshot
   761     {
   762       SmartGraph *_graph;
   763     protected:
   764       friend class SmartGraph;
   765       unsigned int node_num;
   766       unsigned int arc_num;
   767     public:
   768       ///Default constructor.
   769 
   770       ///Default constructor.
   771       ///To actually make a snapshot you must call save().
   772       ///
   773       Snapshot() : _graph(0) {}
   774       ///Constructor that immediately makes a snapshot
   775 
   776       ///This constructor immediately makes a snapshot of the digraph.
   777       ///\param graph The digraph we make a snapshot of.
   778       Snapshot(SmartGraph &graph) {
   779         graph.saveSnapshot(*this);
   780       }
   781 
   782       ///Make a snapshot.
   783 
   784       ///Make a snapshot of the graph.
   785       ///
   786       ///This function can be called more than once. In case of a repeated
   787       ///call, the previous snapshot gets lost.
   788       ///\param graph The digraph we make the snapshot of.
   789       void save(SmartGraph &graph)
   790       {
   791         graph.saveSnapshot(*this);
   792       }
   793 
   794       ///Undo the changes until a snapshot.
   795 
   796       ///Undo the changes until a snapshot created by save().
   797       ///
   798       ///\note After you restored a state, you cannot restore
   799       ///a later state, in other word you cannot add again the arcs deleted
   800       ///by restore().
   801       void restore()
   802       {
   803         _graph->restoreSnapshot(*this);
   804       }
   805     };
   806   };
   807 
   808 } //namespace lemon
   809 
   810 
   811 #endif //LEMON_SMART_GRAPH_H