lemon/smart_graph.h
author Peter Kovacs <kpeter@inf.elte.hu>
Fri, 07 Nov 2008 12:15:16 +0100
changeset 374 49d9a36b3b84
parent 370 00c8843d491d
child 375 2d87dbd7f8c8
permissions -rw-r--r--
Extend test cases for graphs and digraphs (#172)
     1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library.
     4  *
     5  * Copyright (C) 2003-2008
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     9  * Permission to use, modify and distribute this software is granted
    10  * provided that this copyright notice appears in all copies. For
    11  * precise terms see the accompanying LICENSE file.
    12  *
    13  * This software is provided "AS IS" with no warranty of any kind,
    14  * express or implied, and with no claim as to its suitability for any
    15  * purpose.
    16  *
    17  */
    18 
    19 #ifndef LEMON_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 Graph;
    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 EdgeNumTag;
    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 conforms to the \ref concepts::Digraph "Digraph concept" with
   195   ///an important extra feature that its maps are real \ref
   196   ///concepts::ReferenceMap "reference map"s.
   197   ///
   198   ///\sa concepts::Digraph.
   199   class SmartDigraph : public ExtendedSmartDigraphBase {
   200   public:
   201 
   202     typedef ExtendedSmartDigraphBase Parent;
   203 
   204   private:
   205 
   206     ///SmartDigraph is \e not copy constructible. Use DigraphCopy() instead.
   207 
   208     ///SmartDigraph is \e not copy constructible. Use DigraphCopy() instead.
   209     ///
   210     SmartDigraph(const SmartDigraph &) : ExtendedSmartDigraphBase() {};
   211     ///\brief Assignment of SmartDigraph to another one is \e not allowed.
   212     ///Use DigraphCopy() instead.
   213 
   214     ///Assignment of SmartDigraph to another one is \e not allowed.
   215     ///Use DigraphCopy() instead.
   216     void operator=(const SmartDigraph &) {}
   217 
   218   public:
   219 
   220     /// Constructor
   221 
   222     /// Constructor.
   223     ///
   224     SmartDigraph() {};
   225 
   226     ///Add a new node to the digraph.
   227 
   228     /// \return the new node.
   229     ///
   230     Node addNode() { return Parent::addNode(); }
   231 
   232     ///Add a new arc to the digraph.
   233 
   234     ///Add a new arc to the digraph with source node \c s
   235     ///and target node \c t.
   236     ///\return the new arc.
   237     Arc addArc(const Node& s, const Node& t) {
   238       return Parent::addArc(s, t);
   239     }
   240 
   241     /// \brief Using this it is possible to avoid the superfluous memory
   242     /// allocation.
   243 
   244     /// Using this it is possible to avoid the superfluous memory
   245     /// allocation: if you know that the digraph you want to build will
   246     /// be very large (e.g. it will contain millions of nodes and/or arcs)
   247     /// then it is worth reserving space for this amount before starting
   248     /// to build the digraph.
   249     /// \sa reserveArc
   250     void reserveNode(int n) { nodes.reserve(n); };
   251 
   252     /// \brief Using this it is possible to avoid the superfluous memory
   253     /// allocation.
   254 
   255     /// Using this it is possible to avoid the superfluous memory
   256     /// allocation: if you know that the digraph you want to build will
   257     /// be very large (e.g. it will contain millions of nodes and/or arcs)
   258     /// then it is worth reserving space for this amount before starting
   259     /// to build the digraph.
   260     /// \sa reserveNode
   261     void reserveArc(int m) { arcs.reserve(m); };
   262 
   263     /// \brief Node validity check
   264     ///
   265     /// This function gives back true if the given node is valid,
   266     /// ie. it is a real node of the graph.
   267     ///
   268     /// \warning A removed node (using Snapshot) could become valid again
   269     /// when new nodes are added to the graph.
   270     bool valid(Node n) const { return Parent::valid(n); }
   271 
   272     /// \brief Arc validity check
   273     ///
   274     /// This function gives back true if the given arc is valid,
   275     /// ie. it is a real arc of the graph.
   276     ///
   277     /// \warning A removed arc (using Snapshot) could become valid again
   278     /// when new arcs are added to the graph.
   279     bool valid(Arc a) const { return Parent::valid(a); }
   280 
   281     ///Clear the digraph.
   282 
   283     ///Erase all the nodes and arcs from the digraph.
   284     ///
   285     void clear() {
   286       Parent::clear();
   287     }
   288 
   289     ///Split a node.
   290 
   291     ///This function splits a node. First a new node is added to the digraph,
   292     ///then the source of each outgoing arc of \c n is moved to this new node.
   293     ///If \c connect is \c true (this is the default value), then a new arc
   294     ///from \c n to the newly created node is also added.
   295     ///\return The newly created node.
   296     ///
   297     ///\note The <tt>Arc</tt>s
   298     ///referencing a moved arc remain
   299     ///valid. However <tt>InArc</tt>'s and <tt>OutArc</tt>'s
   300     ///may be invalidated.
   301     ///\warning This functionality cannot be used together with the Snapshot
   302     ///feature.
   303     Node split(Node n, bool connect = true)
   304     {
   305       Node b = addNode();
   306       nodes[b._id].first_out=nodes[n._id].first_out;
   307       nodes[n._id].first_out=-1;
   308       for(int i=nodes[b._id].first_out; i!=-1; i=arcs[i].next_out) {
   309         arcs[i].source=b._id;
   310       }
   311       if(connect) addArc(n,b);
   312       return b;
   313     }
   314 
   315   public:
   316 
   317     class Snapshot;
   318 
   319   protected:
   320 
   321     void restoreSnapshot(const Snapshot &s)
   322     {
   323       while(s.arc_num<arcs.size()) {
   324         Arc arc = arcFromId(arcs.size()-1);
   325         Parent::notifier(Arc()).erase(arc);
   326         nodes[arcs.back().source].first_out=arcs.back().next_out;
   327         nodes[arcs.back().target].first_in=arcs.back().next_in;
   328         arcs.pop_back();
   329       }
   330       while(s.node_num<nodes.size()) {
   331         Node node = nodeFromId(nodes.size()-1);
   332         Parent::notifier(Node()).erase(node);
   333         nodes.pop_back();
   334       }
   335     }
   336 
   337   public:
   338 
   339     ///Class to make a snapshot of the digraph and to restrore to it later.
   340 
   341     ///Class to make a snapshot of the digraph and to restrore to it later.
   342     ///
   343     ///The newly added nodes and arcs can be removed using the
   344     ///restore() function.
   345     ///\note After you restore a state, you cannot restore
   346     ///a later state, in other word you cannot add again the arcs deleted
   347     ///by restore() using another one Snapshot instance.
   348     ///
   349     ///\warning If you do not use correctly the snapshot that can cause
   350     ///either broken program, invalid state of the digraph, valid but
   351     ///not the restored digraph or no change. Because the runtime performance
   352     ///the validity of the snapshot is not stored.
   353     class Snapshot
   354     {
   355       SmartDigraph *_graph;
   356     protected:
   357       friend class SmartDigraph;
   358       unsigned int node_num;
   359       unsigned int arc_num;
   360     public:
   361       ///Default constructor.
   362 
   363       ///Default constructor.
   364       ///To actually make a snapshot you must call save().
   365       ///
   366       Snapshot() : _graph(0) {}
   367       ///Constructor that immediately makes a snapshot
   368 
   369       ///This constructor immediately makes a snapshot of the digraph.
   370       ///\param graph The digraph we make a snapshot of.
   371       Snapshot(SmartDigraph &graph) : _graph(&graph) {
   372         node_num=_graph->nodes.size();
   373         arc_num=_graph->arcs.size();
   374       }
   375 
   376       ///Make a snapshot.
   377 
   378       ///Make a snapshot of the digraph.
   379       ///
   380       ///This function can be called more than once. In case of a repeated
   381       ///call, the previous snapshot gets lost.
   382       ///\param graph The digraph we make the snapshot of.
   383       void save(SmartDigraph &graph)
   384       {
   385         _graph=&graph;
   386         node_num=_graph->nodes.size();
   387         arc_num=_graph->arcs.size();
   388       }
   389 
   390       ///Undo the changes until a snapshot.
   391 
   392       ///Undo the changes until a snapshot created by save().
   393       ///
   394       ///\note After you restored a state, you cannot restore
   395       ///a later state, in other word you cannot add again the arcs deleted
   396       ///by restore().
   397       void restore()
   398       {
   399         _graph->restoreSnapshot(*this);
   400       }
   401     };
   402   };
   403 
   404 
   405   class SmartGraphBase {
   406 
   407   protected:
   408 
   409     struct NodeT {
   410       int first_out;
   411     };
   412 
   413     struct ArcT {
   414       int target;
   415       int next_out;
   416     };
   417 
   418     std::vector<NodeT> nodes;
   419     std::vector<ArcT> arcs;
   420 
   421     int first_free_arc;
   422 
   423   public:
   424 
   425     typedef SmartGraphBase Digraph;
   426 
   427     class Node;
   428     class Arc;
   429     class Edge;
   430 
   431     class Node {
   432       friend class SmartGraphBase;
   433     protected:
   434 
   435       int _id;
   436       explicit Node(int id) { _id = id;}
   437 
   438     public:
   439       Node() {}
   440       Node (Invalid) { _id = -1; }
   441       bool operator==(const Node& node) const {return _id == node._id;}
   442       bool operator!=(const Node& node) const {return _id != node._id;}
   443       bool operator<(const Node& node) const {return _id < node._id;}
   444     };
   445 
   446     class Edge {
   447       friend class SmartGraphBase;
   448     protected:
   449 
   450       int _id;
   451       explicit Edge(int id) { _id = id;}
   452 
   453     public:
   454       Edge() {}
   455       Edge (Invalid) { _id = -1; }
   456       bool operator==(const Edge& arc) const {return _id == arc._id;}
   457       bool operator!=(const Edge& arc) const {return _id != arc._id;}
   458       bool operator<(const Edge& arc) const {return _id < arc._id;}
   459     };
   460 
   461     class Arc {
   462       friend class SmartGraphBase;
   463     protected:
   464 
   465       int _id;
   466       explicit Arc(int id) { _id = id;}
   467 
   468     public:
   469       operator Edge() const { 
   470         return _id != -1 ? edgeFromId(_id / 2) : INVALID; 
   471       }
   472 
   473       Arc() {}
   474       Arc (Invalid) { _id = -1; }
   475       bool operator==(const Arc& arc) const {return _id == arc._id;}
   476       bool operator!=(const Arc& arc) const {return _id != arc._id;}
   477       bool operator<(const Arc& arc) const {return _id < arc._id;}
   478     };
   479 
   480 
   481 
   482     SmartGraphBase()
   483       : nodes(), arcs() {}
   484 
   485 
   486     int maxNodeId() const { return nodes.size()-1; }
   487     int maxEdgeId() const { return arcs.size() / 2 - 1; }
   488     int maxArcId() const { return arcs.size()-1; }
   489 
   490     Node source(Arc e) const { return Node(arcs[e._id ^ 1].target); }
   491     Node target(Arc e) const { return Node(arcs[e._id].target); }
   492 
   493     Node u(Edge e) const { return Node(arcs[2 * e._id].target); }
   494     Node v(Edge e) const { return Node(arcs[2 * e._id + 1].target); }
   495 
   496     static bool direction(Arc e) {
   497       return (e._id & 1) == 1;
   498     }
   499 
   500     static Arc direct(Edge e, bool d) {
   501       return Arc(e._id * 2 + (d ? 1 : 0));
   502     }
   503 
   504     void first(Node& node) const {
   505       node._id = nodes.size() - 1;
   506     }
   507 
   508     void next(Node& node) const {
   509       --node._id;
   510     }
   511 
   512     void first(Arc& arc) const {
   513       arc._id = arcs.size() - 1;
   514     }
   515 
   516     void next(Arc& arc) const {
   517       --arc._id;
   518     }
   519 
   520     void first(Edge& arc) const {
   521       arc._id = arcs.size() / 2 - 1;
   522     }
   523 
   524     void next(Edge& arc) const {
   525       --arc._id;
   526     }
   527 
   528     void firstOut(Arc &arc, const Node& v) const {
   529       arc._id = nodes[v._id].first_out;
   530     }
   531     void nextOut(Arc &arc) const {
   532       arc._id = arcs[arc._id].next_out;
   533     }
   534 
   535     void firstIn(Arc &arc, const Node& v) const {
   536       arc._id = ((nodes[v._id].first_out) ^ 1);
   537       if (arc._id == -2) arc._id = -1;
   538     }
   539     void nextIn(Arc &arc) const {
   540       arc._id = ((arcs[arc._id ^ 1].next_out) ^ 1);
   541       if (arc._id == -2) arc._id = -1;
   542     }
   543 
   544     void firstInc(Edge &arc, bool& d, const Node& v) const {
   545       int de = nodes[v._id].first_out;
   546       if (de != -1) {
   547         arc._id = de / 2;
   548         d = ((de & 1) == 1);
   549       } else {
   550         arc._id = -1;
   551         d = true;
   552       }
   553     }
   554     void nextInc(Edge &arc, bool& d) const {
   555       int de = (arcs[(arc._id * 2) | (d ? 1 : 0)].next_out);
   556       if (de != -1) {
   557         arc._id = de / 2;
   558         d = ((de & 1) == 1);
   559       } else {
   560         arc._id = -1;
   561         d = true;
   562       }
   563     }
   564 
   565     static int id(Node v) { return v._id; }
   566     static int id(Arc e) { return e._id; }
   567     static int id(Edge e) { return e._id; }
   568 
   569     static Node nodeFromId(int id) { return Node(id);}
   570     static Arc arcFromId(int id) { return Arc(id);}
   571     static Edge edgeFromId(int id) { return Edge(id);}
   572 
   573     bool valid(Node n) const {
   574       return n._id >= 0 && n._id < static_cast<int>(nodes.size());
   575     }
   576     bool valid(Arc a) const {
   577       return a._id >= 0 && a._id < static_cast<int>(arcs.size());
   578     }
   579     bool valid(Edge e) const {
   580       return e._id >= 0 && 2 * e._id < static_cast<int>(arcs.size());
   581     }
   582 
   583     Node addNode() {
   584       int n = nodes.size();
   585       nodes.push_back(NodeT());
   586       nodes[n].first_out = -1;
   587 
   588       return Node(n);
   589     }
   590 
   591     Edge addEdge(Node u, Node v) {
   592       int n = arcs.size();
   593       arcs.push_back(ArcT());
   594       arcs.push_back(ArcT());
   595 
   596       arcs[n].target = u._id;
   597       arcs[n | 1].target = v._id;
   598 
   599       arcs[n].next_out = nodes[v._id].first_out;
   600       nodes[v._id].first_out = n;
   601 
   602       arcs[n | 1].next_out = nodes[u._id].first_out;
   603       nodes[u._id].first_out = (n | 1);
   604 
   605       return Edge(n / 2);
   606     }
   607 
   608     void clear() {
   609       arcs.clear();
   610       nodes.clear();
   611     }
   612 
   613   };
   614 
   615   typedef GraphExtender<SmartGraphBase> ExtendedSmartGraphBase;
   616 
   617   /// \ingroup graphs
   618   ///
   619   /// \brief A smart undirected graph class.
   620   ///
   621   /// This is a simple and fast graph implementation.
   622   /// It is also quite memory efficient, but at the price
   623   /// that <b> it does support only limited (only stack-like)
   624   /// node and arc deletions</b>.
   625   /// Except from this it conforms to
   626   /// the \ref concepts::Graph "Graph concept".
   627   ///
   628   /// It also has an
   629   /// important extra feature that
   630   /// its maps are real \ref concepts::ReferenceMap "reference map"s.
   631   ///
   632   /// \sa concepts::Graph.
   633   ///
   634   class SmartGraph : public ExtendedSmartGraphBase {
   635   private:
   636 
   637     ///SmartGraph is \e not copy constructible. Use GraphCopy() instead.
   638 
   639     ///SmartGraph is \e not copy constructible. Use GraphCopy() instead.
   640     ///
   641     SmartGraph(const SmartGraph &) : ExtendedSmartGraphBase() {};
   642 
   643     ///\brief Assignment of SmartGraph to another one is \e not allowed.
   644     ///Use GraphCopy() instead.
   645 
   646     ///Assignment of SmartGraph to another one is \e not allowed.
   647     ///Use GraphCopy() instead.
   648     void operator=(const SmartGraph &) {}
   649 
   650   public:
   651 
   652     typedef ExtendedSmartGraphBase Parent;
   653 
   654     /// Constructor
   655 
   656     /// Constructor.
   657     ///
   658     SmartGraph() {}
   659 
   660     ///Add a new node to the graph.
   661 
   662     /// \return the new node.
   663     ///
   664     Node addNode() { return Parent::addNode(); }
   665 
   666     ///Add a new edge to the graph.
   667 
   668     ///Add a new edge to the graph with node \c s
   669     ///and \c t.
   670     ///\return the new edge.
   671     Edge addEdge(const Node& s, const Node& t) {
   672       return Parent::addEdge(s, t);
   673     }
   674 
   675     /// \brief Node validity check
   676     ///
   677     /// This function gives back true if the given node is valid,
   678     /// ie. it is a real node of the graph.
   679     ///
   680     /// \warning A removed node (using Snapshot) could become valid again
   681     /// when new nodes are added to the graph.
   682     bool valid(Node n) const { return Parent::valid(n); }
   683 
   684     /// \brief Arc validity check
   685     ///
   686     /// This function gives back true if the given arc is valid,
   687     /// ie. it is a real arc of the graph.
   688     ///
   689     /// \warning A removed arc (using Snapshot) could become valid again
   690     /// when new edges are added to the graph.
   691     bool valid(Arc a) const { return Parent::valid(a); }
   692 
   693     /// \brief Edge validity check
   694     ///
   695     /// This function gives back true if the given edge is valid,
   696     /// ie. it is a real edge of the graph.
   697     ///
   698     /// \warning A removed edge (using Snapshot) could become valid again
   699     /// when new edges are added to the graph.
   700     bool valid(Edge e) const { return Parent::valid(e); }
   701 
   702     ///Clear the graph.
   703 
   704     ///Erase all the nodes and edges from the graph.
   705     ///
   706     void clear() {
   707       Parent::clear();
   708     }
   709 
   710   public:
   711 
   712     class Snapshot;
   713 
   714   protected:
   715 
   716     void saveSnapshot(Snapshot &s)
   717     {
   718       s._graph = this;
   719       s.node_num = nodes.size();
   720       s.arc_num = arcs.size();
   721     }
   722 
   723     void restoreSnapshot(const Snapshot &s)
   724     {
   725       while(s.arc_num<arcs.size()) {
   726         int n=arcs.size()-1;
   727         Edge arc=edgeFromId(n/2);
   728         Parent::notifier(Edge()).erase(arc);
   729         std::vector<Arc> dir;
   730         dir.push_back(arcFromId(n));
   731         dir.push_back(arcFromId(n-1));
   732         Parent::notifier(Arc()).erase(dir);
   733         nodes[arcs[n-1].target].first_out=arcs[n].next_out;
   734         nodes[arcs[n].target].first_out=arcs[n-1].next_out;
   735         arcs.pop_back();
   736         arcs.pop_back();
   737       }
   738       while(s.node_num<nodes.size()) {
   739         int n=nodes.size()-1;
   740         Node node = nodeFromId(n);
   741         Parent::notifier(Node()).erase(node);
   742         nodes.pop_back();
   743       }
   744     }
   745 
   746   public:
   747 
   748     ///Class to make a snapshot of the digraph and to restrore to it later.
   749 
   750     ///Class to make a snapshot of the digraph and to restrore to it later.
   751     ///
   752     ///The newly added nodes and arcs can be removed using the
   753     ///restore() function.
   754     ///
   755     ///\note After you restore a state, you cannot restore
   756     ///a later state, in other word you cannot add again the arcs deleted
   757     ///by restore() using another one Snapshot instance.
   758     ///
   759     ///\warning If you do not use correctly the snapshot that can cause
   760     ///either broken program, invalid state of the digraph, valid but
   761     ///not the restored digraph or no change. Because the runtime performance
   762     ///the validity of the snapshot is not stored.
   763     class Snapshot
   764     {
   765       SmartGraph *_graph;
   766     protected:
   767       friend class SmartGraph;
   768       unsigned int node_num;
   769       unsigned int arc_num;
   770     public:
   771       ///Default constructor.
   772 
   773       ///Default constructor.
   774       ///To actually make a snapshot you must call save().
   775       ///
   776       Snapshot() : _graph(0) {}
   777       ///Constructor that immediately makes a snapshot
   778 
   779       ///This constructor immediately makes a snapshot of the digraph.
   780       ///\param graph The digraph we make a snapshot of.
   781       Snapshot(SmartGraph &graph) {
   782         graph.saveSnapshot(*this);
   783       }
   784 
   785       ///Make a snapshot.
   786 
   787       ///Make a snapshot of the graph.
   788       ///
   789       ///This function can be called more than once. In case of a repeated
   790       ///call, the previous snapshot gets lost.
   791       ///\param graph The digraph we make the snapshot of.
   792       void save(SmartGraph &graph)
   793       {
   794         graph.saveSnapshot(*this);
   795       }
   796 
   797       ///Undo the changes until a snapshot.
   798 
   799       ///Undo the changes until a snapshot created by save().
   800       ///
   801       ///\note After you restored a state, you cannot restore
   802       ///a later state, in other word you cannot add again the arcs deleted
   803       ///by restore().
   804       void restore()
   805       {
   806         _graph->restoreSnapshot(*this);
   807       }
   808     };
   809   };
   810 
   811 } //namespace lemon
   812 
   813 
   814 #endif //LEMON_SMART_GRAPH_H