lemon/smart_graph.h
 author Alpar Juttner Mon, 23 Feb 2009 15:46:57 +0000 changeset 379 39aaeea2d471 parent 280 e7f8647ce760 child 335 00c8843d491d permissions -rw-r--r--
Include /lemon/config.h globally (#230)
     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].source=b._id;

   309       if(connect) addArc(n,b);

   310       return b;

   311     }

   312

   313   public:

   314

   315     class Snapshot;

   316

   317   protected:

   318

   319     void restoreSnapshot(const Snapshot &s)

   320     {

   321       while(s.arc_num<arcs.size()) {

   322         Arc arc = arcFromId(arcs.size()-1);

   323         Parent::notifier(Arc()).erase(arc);

   324         nodes[arcs.back().source].first_out=arcs.back().next_out;

   325         nodes[arcs.back().target].first_in=arcs.back().next_in;

   326         arcs.pop_back();

   327       }

   328       while(s.node_num<nodes.size()) {

   329         Node node = nodeFromId(nodes.size()-1);

   330         Parent::notifier(Node()).erase(node);

   331         nodes.pop_back();

   332       }

   333     }

   334

   335   public:

   336

   337     ///Class to make a snapshot of the digraph and to restrore to it later.

   338

   339     ///Class to make a snapshot of the digraph and to restrore to it later.

   340     ///

   341     ///The newly added nodes and arcs can be removed using the

   342     ///restore() function.

   343     ///\note After you restore a state, you cannot restore

   344     ///a later state, in other word you cannot add again the arcs deleted

   345     ///by restore() using another one Snapshot instance.

   346     ///

   347     ///\warning If you do not use correctly the snapshot that can cause

   348     ///either broken program, invalid state of the digraph, valid but

   349     ///not the restored digraph or no change. Because the runtime performance

   350     ///the validity of the snapshot is not stored.

   351     class Snapshot

   352     {

   353       SmartDigraph *_graph;

   354     protected:

   355       friend class SmartDigraph;

   356       unsigned int node_num;

   357       unsigned int arc_num;

   358     public:

   359       ///Default constructor.

   360

   361       ///Default constructor.

   362       ///To actually make a snapshot you must call save().

   363       ///

   364       Snapshot() : _graph(0) {}

   365       ///Constructor that immediately makes a snapshot

   366

   367       ///This constructor immediately makes a snapshot of the digraph.

   368       ///\param graph The digraph we make a snapshot of.

   369       Snapshot(SmartDigraph &graph) : _graph(&graph) {

   370         node_num=_graph->nodes.size();

   371         arc_num=_graph->arcs.size();

   372       }

   373

   374       ///Make a snapshot.

   375

   376       ///Make a snapshot of the digraph.

   377       ///

   378       ///This function can be called more than once. In case of a repeated

   379       ///call, the previous snapshot gets lost.

   380       ///\param graph The digraph we make the snapshot of.

   381       void save(SmartDigraph &graph)

   382       {

   383         _graph=&graph;

   384         node_num=_graph->nodes.size();

   385         arc_num=_graph->arcs.size();

   386       }

   387

   388       ///Undo the changes until a snapshot.

   389

   390       ///Undo the changes until a snapshot created by save().

   391       ///

   392       ///\note After you restored a state, you cannot restore

   393       ///a later state, in other word you cannot add again the arcs deleted

   394       ///by restore().

   395       void restore()

   396       {

   397         _graph->restoreSnapshot(*this);

   398       }

   399     };

   400   };

   401

   402

   403   class SmartGraphBase {

   404

   405   protected:

   406

   407     struct NodeT {

   408       int first_out;

   409     };

   410

   411     struct ArcT {

   412       int target;

   413       int next_out;

   414     };

   415

   416     std::vector<NodeT> nodes;

   417     std::vector<ArcT> arcs;

   418

   419     int first_free_arc;

   420

   421   public:

   422

   423     typedef SmartGraphBase Digraph;

   424

   425     class Node;

   426     class Arc;

   427     class Edge;

   428

   429     class Node {

   430       friend class SmartGraphBase;

   431     protected:

   432

   433       int _id;

   434       explicit Node(int id) { _id = id;}

   435

   436     public:

   437       Node() {}

   438       Node (Invalid) { _id = -1; }

   439       bool operator==(const Node& node) const {return _id == node._id;}

   440       bool operator!=(const Node& node) const {return _id != node._id;}

   441       bool operator<(const Node& node) const {return _id < node._id;}

   442     };

   443

   444     class Edge {

   445       friend class SmartGraphBase;

   446     protected:

   447

   448       int _id;

   449       explicit Edge(int id) { _id = id;}

   450

   451     public:

   452       Edge() {}

   453       Edge (Invalid) { _id = -1; }

   454       bool operator==(const Edge& arc) const {return _id == arc._id;}

   455       bool operator!=(const Edge& arc) const {return _id != arc._id;}

   456       bool operator<(const Edge& arc) const {return _id < arc._id;}

   457     };

   458

   459     class Arc {

   460       friend class SmartGraphBase;

   461     protected:

   462

   463       int _id;

   464       explicit Arc(int id) { _id = id;}

   465

   466     public:

   467       operator Edge() const {

   468         return _id != -1 ? edgeFromId(_id / 2) : INVALID;

   469       }

   470

   471       Arc() {}

   472       Arc (Invalid) { _id = -1; }

   473       bool operator==(const Arc& arc) const {return _id == arc._id;}

   474       bool operator!=(const Arc& arc) const {return _id != arc._id;}

   475       bool operator<(const Arc& arc) const {return _id < arc._id;}

   476     };

   477

   478

   479

   480     SmartGraphBase()

   481       : nodes(), arcs() {}

   482

   483

   484     int maxNodeId() const { return nodes.size()-1; }

   485     int maxEdgeId() const { return arcs.size() / 2 - 1; }

   486     int maxArcId() const { return arcs.size()-1; }

   487

   488     Node source(Arc e) const { return Node(arcs[e._id ^ 1].target); }

   489     Node target(Arc e) const { return Node(arcs[e._id].target); }

   490

   491     Node u(Edge e) const { return Node(arcs[2 * e._id].target); }

   492     Node v(Edge e) const { return Node(arcs[2 * e._id + 1].target); }

   493

   494     static bool direction(Arc e) {

   495       return (e._id & 1) == 1;

   496     }

   497

   498     static Arc direct(Edge e, bool d) {

   499       return Arc(e._id * 2 + (d ? 1 : 0));

   500     }

   501

   502     void first(Node& node) const {

   503       node._id = nodes.size() - 1;

   504     }

   505

   506     void next(Node& node) const {

   507       --node._id;

   508     }

   509

   510     void first(Arc& arc) const {

   511       arc._id = arcs.size() - 1;

   512     }

   513

   514     void next(Arc& arc) const {

   515       --arc._id;

   516     }

   517

   518     void first(Edge& arc) const {

   519       arc._id = arcs.size() / 2 - 1;

   520     }

   521

   522     void next(Edge& arc) const {

   523       --arc._id;

   524     }

   525

   526     void firstOut(Arc &arc, const Node& v) const {

   527       arc._id = nodes[v._id].first_out;

   528     }

   529     void nextOut(Arc &arc) const {

   530       arc._id = arcs[arc._id].next_out;

   531     }

   532

   533     void firstIn(Arc &arc, const Node& v) const {

   534       arc._id = ((nodes[v._id].first_out) ^ 1);

   535       if (arc._id == -2) arc._id = -1;

   536     }

   537     void nextIn(Arc &arc) const {

   538       arc._id = ((arcs[arc._id ^ 1].next_out) ^ 1);

   539       if (arc._id == -2) arc._id = -1;

   540     }

   541

   542     void firstInc(Edge &arc, bool& d, const Node& v) const {

   543       int de = nodes[v._id].first_out;

   544       if (de != -1) {

   545         arc._id = de / 2;

   546         d = ((de & 1) == 1);

   547       } else {

   548         arc._id = -1;

   549         d = true;

   550       }

   551     }

   552     void nextInc(Edge &arc, bool& d) const {

   553       int de = (arcs[(arc._id * 2) | (d ? 1 : 0)].next_out);

   554       if (de != -1) {

   555         arc._id = de / 2;

   556         d = ((de & 1) == 1);

   557       } else {

   558         arc._id = -1;

   559         d = true;

   560       }

   561     }

   562

   563     static int id(Node v) { return v._id; }

   564     static int id(Arc e) { return e._id; }

   565     static int id(Edge e) { return e._id; }

   566

   567     static Node nodeFromId(int id) { return Node(id);}

   568     static Arc arcFromId(int id) { return Arc(id);}

   569     static Edge edgeFromId(int id) { return Edge(id);}

   570

   571     bool valid(Node n) const {

   572       return n._id >= 0 && n._id < static_cast<int>(nodes.size());

   573     }

   574     bool valid(Arc a) const {

   575       return a._id >= 0 && a._id < static_cast<int>(arcs.size());

   576     }

   577     bool valid(Edge e) const {

   578       return e._id >= 0 && 2 * e._id < static_cast<int>(arcs.size());

   579     }

   580

   581     Node addNode() {

   582       int n = nodes.size();

   583       nodes.push_back(NodeT());

   584       nodes[n].first_out = -1;

   585

   586       return Node(n);

   587     }

   588

   589     Edge addEdge(Node u, Node v) {

   590       int n = arcs.size();

   591       arcs.push_back(ArcT());

   592       arcs.push_back(ArcT());

   593

   594       arcs[n].target = u._id;

   595       arcs[n | 1].target = v._id;

   596

   597       arcs[n].next_out = nodes[v._id].first_out;

   598       nodes[v._id].first_out = n;

   599

   600       arcs[n | 1].next_out = nodes[u._id].first_out;

   601       nodes[u._id].first_out = (n | 1);

   602

   603       return Edge(n / 2);

   604     }

   605

   606     void clear() {

   607       arcs.clear();

   608       nodes.clear();

   609     }

   610

   611   };

   612

   613   typedef GraphExtender<SmartGraphBase> ExtendedSmartGraphBase;

   614

   615   /// \ingroup graphs

   616   ///

   617   /// \brief A smart undirected graph class.

   618   ///

   619   /// This is a simple and fast graph implementation.

   620   /// It is also quite memory efficient, but at the price

   621   /// that <b> it does support only limited (only stack-like)

   622   /// node and arc deletions</b>.

   623   /// Except from this it conforms to

   624   /// the \ref concepts::Graph "Graph concept".

   625   ///

   626   /// It also has an

   627   /// important extra feature that

   628   /// its maps are real \ref concepts::ReferenceMap "reference map"s.

   629   ///

   630   /// \sa concepts::Graph.

   631   ///

   632   class SmartGraph : public ExtendedSmartGraphBase {

   633   private:

   634

   635     ///SmartGraph is \e not copy constructible. Use GraphCopy() instead.

   636

   637     ///SmartGraph is \e not copy constructible. Use GraphCopy() instead.

   638     ///

   639     SmartGraph(const SmartGraph &) : ExtendedSmartGraphBase() {};

   640

   641     ///\brief Assignment of SmartGraph to another one is \e not allowed.

   642     ///Use GraphCopy() instead.

   643

   644     ///Assignment of SmartGraph to another one is \e not allowed.

   645     ///Use GraphCopy() instead.

   646     void operator=(const SmartGraph &) {}

   647

   648   public:

   649

   650     typedef ExtendedSmartGraphBase Parent;

   651

   652     /// Constructor

   653

   654     /// Constructor.

   655     ///

   656     SmartGraph() {}

   657

   658     ///Add a new node to the graph.

   659

   660     /// \return the new node.

   661     ///

   662     Node addNode() { return Parent::addNode(); }

   663

   664     ///Add a new edge to the graph.

   665

   666     ///Add a new edge to the graph with node \c s

   667     ///and \c t.

   668     ///\return the new edge.

   669     Edge addEdge(const Node& s, const Node& t) {

   670       return Parent::addEdge(s, t);

   671     }

   672

   673     /// \brief Node validity check

   674     ///

   675     /// This function gives back true if the given node is valid,

   676     /// ie. it is a real node of the graph.

   677     ///

   678     /// \warning A removed node (using Snapshot) could become valid again

   679     /// when new nodes are added to the graph.

   680     bool valid(Node n) const { return Parent::valid(n); }

   681

   682     /// \brief Arc validity check

   683     ///

   684     /// This function gives back true if the given arc is valid,

   685     /// ie. it is a real arc of the graph.

   686     ///

   687     /// \warning A removed arc (using Snapshot) could become valid again

   688     /// when new edges are added to the graph.

   689     bool valid(Arc a) const { return Parent::valid(a); }

   690

   691     /// \brief Edge validity check

   692     ///

   693     /// This function gives back true if the given edge is valid,

   694     /// ie. it is a real edge of the graph.

   695     ///

   696     /// \warning A removed edge (using Snapshot) could become valid again

   697     /// when new edges are added to the graph.

   698     bool valid(Edge e) const { return Parent::valid(e); }

   699

   700     ///Clear the graph.

   701

   702     ///Erase all the nodes and edges from the graph.

   703     ///

   704     void clear() {

   705       Parent::clear();

   706     }

   707

   708   public:

   709

   710     class Snapshot;

   711

   712   protected:

   713

   714     void saveSnapshot(Snapshot &s)

   715     {

   716       s._graph = this;

   717       s.node_num = nodes.size();

   718       s.arc_num = arcs.size();

   719     }

   720

   721     void restoreSnapshot(const Snapshot &s)

   722     {

   723       while(s.arc_num<arcs.size()) {

   724         int n=arcs.size()-1;

   725         Edge arc=edgeFromId(n/2);

   726         Parent::notifier(Edge()).erase(arc);

   727         std::vector<Arc> dir;

   728         dir.push_back(arcFromId(n));

   729         dir.push_back(arcFromId(n-1));

   730         Parent::notifier(Arc()).erase(dir);

   731         nodes[arcs[n].target].first_out=arcs[n].next_out;

   732         nodes[arcs[n-1].target].first_out=arcs[n-1].next_out;

   733         arcs.pop_back();

   734         arcs.pop_back();

   735       }

   736       while(s.node_num<nodes.size()) {

   737         int n=nodes.size()-1;

   738         Node node = nodeFromId(n);

   739         Parent::notifier(Node()).erase(node);

   740         nodes.pop_back();

   741       }

   742     }

   743

   744   public:

   745

   746     ///Class to make a snapshot of the digraph and to restrore to it later.

   747

   748     ///Class to make a snapshot of the digraph and to restrore to it later.

   749     ///

   750     ///The newly added nodes and arcs can be removed using the

   751     ///restore() function.

   752     ///

   753     ///\note After you restore a state, you cannot restore

   754     ///a later state, in other word you cannot add again the arcs deleted

   755     ///by restore() using another one Snapshot instance.

   756     ///

   757     ///\warning If you do not use correctly the snapshot that can cause

   758     ///either broken program, invalid state of the digraph, valid but

   759     ///not the restored digraph or no change. Because the runtime performance

   760     ///the validity of the snapshot is not stored.

   761     class Snapshot

   762     {

   763       SmartGraph *_graph;

   764     protected:

   765       friend class SmartGraph;

   766       unsigned int node_num;

   767       unsigned int arc_num;

   768     public:

   769       ///Default constructor.

   770

   771       ///Default constructor.

   772       ///To actually make a snapshot you must call save().

   773       ///

   774       Snapshot() : _graph(0) {}

   775       ///Constructor that immediately makes a snapshot

   776

   777       ///This constructor immediately makes a snapshot of the digraph.

   778       ///\param graph The digraph we make a snapshot of.

   779       Snapshot(SmartGraph &graph) {

   780         graph.saveSnapshot(*this);

   781       }

   782

   783       ///Make a snapshot.

   784

   785       ///Make a snapshot of the graph.

   786       ///

   787       ///This function can be called more than once. In case of a repeated

   788       ///call, the previous snapshot gets lost.

   789       ///\param graph The digraph we make the snapshot of.

   790       void save(SmartGraph &graph)

   791       {

   792         graph.saveSnapshot(*this);

   793       }

   794

   795       ///Undo the changes until a snapshot.

   796

   797       ///Undo the changes until a snapshot created by save().

   798       ///

   799       ///\note After you restored a state, you cannot restore

   800       ///a later state, in other word you cannot add again the arcs deleted

   801       ///by restore().

   802       void restore()

   803       {

   804         _graph->restoreSnapshot(*this);

   805       }

   806     };

   807   };

   808

   809 } //namespace lemon

   810

   811

   812 #endif //LEMON_SMART_GRAPH_H