lemon/smart_graph.h
author alpar
Thu, 12 Oct 2006 10:56:26 +0000
changeset 2237 5674a5983e1e
parent 2190 dd887831e9c1
child 2256 b22dfb6c5ff3
permissions -rw-r--r--
Improve the configuration environment / repository layout:
- Update README
- svn-head -> svnhead version tag change (in favor of rpm build)
- rpmbuild-glpk: a script to build glpk rpm.
     1 /* -*- C++ -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library
     4  *
     5  * Copyright (C) 2003-2006
     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 SmartGraph and SmartUGraph classes.
    25 
    26 #include <vector>
    27 
    28 #include <lemon/bits/invalid.h>
    29 
    30 #include <lemon/bits/base_extender.h>
    31 #include <lemon/bits/graph_extender.h>
    32 
    33 #include <lemon/bits/utility.h>
    34 #include <lemon/error.h>
    35 
    36 #include <lemon/bits/graph_extender.h>
    37 
    38 namespace lemon {
    39 
    40   class SmartGraph;
    41   ///Base of SmartGraph
    42 
    43   ///Base of SmartGraph
    44   ///
    45   class SmartGraphBase {
    46   protected:
    47 
    48     struct NodeT 
    49     {
    50       int first_in, first_out;      
    51       NodeT() {}
    52     };
    53     struct EdgeT 
    54     {
    55       int target, source, next_in, next_out;      
    56       EdgeT() {}  
    57     };
    58 
    59     std::vector<NodeT> nodes;
    60 
    61     std::vector<EdgeT> edges;
    62     
    63     
    64   public:
    65 
    66     typedef SmartGraphBase Graph;
    67 
    68     class Node;
    69     class Edge;
    70 
    71     
    72   public:
    73 
    74     SmartGraphBase() : nodes(), edges() { }
    75     SmartGraphBase(const SmartGraphBase &_g) 
    76       : nodes(_g.nodes), edges(_g.edges) { }
    77     
    78     typedef True NodeNumTag;
    79     typedef True EdgeNumTag;
    80 
    81     int nodeNum() const { return nodes.size(); }
    82     int edgeNum() const { return edges.size(); }
    83 
    84     int maxNodeId() const { return nodes.size()-1; }
    85     int maxEdgeId() const { return edges.size()-1; }
    86 
    87     Node addNode() {
    88       int n = nodes.size();     
    89       nodes.push_back(NodeT());
    90       nodes[n].first_in = -1;
    91       nodes[n].first_out = -1;
    92       return Node(n);
    93     }
    94     
    95     Edge addEdge(Node u, Node v) {
    96       int n = edges.size(); 
    97       edges.push_back(EdgeT());
    98       edges[n].source = u.id; 
    99       edges[n].target = v.id;
   100       edges[n].next_out = nodes[u.id].first_out;
   101       edges[n].next_in = nodes[v.id].first_in;
   102       nodes[u.id].first_out = nodes[v.id].first_in = n;
   103 
   104       return Edge(n);
   105     }
   106 
   107     void clear() {
   108       edges.clear();
   109       nodes.clear();
   110     }
   111 
   112     Node source(Edge e) const { return Node(edges[e.id].source); }
   113     Node target(Edge e) const { return Node(edges[e.id].target); }
   114 
   115     static int id(Node v) { return v.id; }
   116     static int id(Edge e) { return e.id; }
   117 
   118     static Node nodeFromId(int id) { return Node(id);}
   119     static Edge edgeFromId(int id) { return Edge(id);}
   120 
   121     class Node {
   122       friend class SmartGraphBase;
   123       friend class SmartGraph;
   124 
   125     protected:
   126       int id;
   127       explicit Node(int _id) : id(_id) {}
   128     public:
   129       Node() {}
   130       Node (Invalid) : id(-1) {}
   131       bool operator==(const Node i) const {return id == i.id;}
   132       bool operator!=(const Node i) const {return id != i.id;}
   133       bool operator<(const Node i) const {return id < i.id;}
   134     };
   135     
   136 
   137     class Edge {
   138       friend class SmartGraphBase;
   139       friend class SmartGraph;
   140 
   141     protected:
   142       int id;
   143       explicit Edge(int _id) : id(_id) {}
   144     public:
   145       Edge() { }
   146       Edge (Invalid) : id(-1) {}
   147       bool operator==(const Edge i) const {return id == i.id;}
   148       bool operator!=(const Edge i) const {return id != i.id;}
   149       bool operator<(const Edge i) const {return id < i.id;}
   150     };
   151 
   152     void first(Node& node) const {
   153       node.id = nodes.size() - 1;
   154     }
   155 
   156     static void next(Node& node) {
   157       --node.id;
   158     }
   159 
   160     void first(Edge& edge) const {
   161       edge.id = edges.size() - 1;
   162     }
   163 
   164     static void next(Edge& edge) {
   165       --edge.id;
   166     }
   167 
   168     void firstOut(Edge& edge, const Node& node) const {
   169       edge.id = nodes[node.id].first_out;
   170     }
   171 
   172     void nextOut(Edge& edge) const {
   173       edge.id = edges[edge.id].next_out;
   174     }
   175 
   176     void firstIn(Edge& edge, const Node& node) const {
   177       edge.id = nodes[node.id].first_in;
   178     }
   179     
   180     void nextIn(Edge& edge) const {
   181       edge.id = edges[edge.id].next_in;
   182     }
   183 
   184   };
   185 
   186   typedef GraphExtender<SmartGraphBase> ExtendedSmartGraphBase;
   187 
   188   /// \ingroup graphs
   189 
   190   ///A smart graph class.
   191 
   192   ///This is a simple and fast graph implementation.
   193   ///It is also quite memory efficient, but at the price
   194   ///that <b> it does support only limited (only stack-like)
   195   ///node and edge deletions</b>.
   196   ///It conforms to 
   197   ///the \ref concept::Graph "Graph concept".
   198   ///\sa concept::Graph.
   199   ///
   200   ///\author Alpar Juttner
   201   class SmartGraph : public ExtendedSmartGraphBase {
   202   public:
   203 
   204     typedef ExtendedSmartGraphBase Parent;
   205 
   206   private:
   207 
   208     ///SmartGraph is \e not copy constructible. Use GraphCopy() instead.
   209 
   210     ///SmartGraph is \e not copy constructible. Use GraphCopy() instead.
   211     ///
   212     SmartGraph(const SmartGraph &) : ExtendedSmartGraphBase() {};
   213     ///\brief Assignment of SmartGraph to another one is \e not allowed.
   214     ///Use GraphCopy() instead.
   215 
   216     ///Assignment of SmartGraph to another one is \e not allowed.
   217     ///Use GraphCopy() instead.
   218     void operator=(const SmartGraph &) {}
   219 
   220   public:
   221     
   222     /// Constructor
   223     
   224     /// Constructor.
   225     ///
   226     SmartGraph() {};
   227     
   228     ///Add a new node to the graph.
   229     
   230     /// \return the new node.
   231     ///
   232     Node addNode() { return Parent::addNode(); }
   233     
   234     ///Add a new edge to the graph.
   235     
   236     ///Add a new edge to the graph with source node \c s
   237     ///and target node \c t.
   238     ///\return the new edge.
   239     Edge addEdge(const Node& s, const Node& t) { 
   240       return Parent::addEdge(s, t); 
   241     }
   242 
   243     ///Clear the graph.
   244     
   245     ///Erase all the nodes and edges from the graph.
   246     ///
   247     void clear() {
   248       Parent::clear();
   249     }
   250 
   251     ///Split a node.
   252     
   253     ///This function splits a node. First a new node is added to the graph,
   254     ///then the source of each outgoing edge of \c n is moved to this new node.
   255     ///If \c connect is \c true (this is the default value), then a new edge
   256     ///from \c n to the newly created node is also added.
   257     ///\return The newly created node.
   258     ///
   259     ///\note The <tt>Edge</tt>s
   260     ///referencing a moved edge remain
   261     ///valid. However <tt>InEdge</tt>'s and <tt>OutEdge</tt>'s
   262     ///may be invalidated.
   263     ///\warning This functionality cannot be used together with the Snapshot
   264     ///feature.
   265     ///\todo It could be implemented in a bit faster way.
   266     Node split(Node n, bool connect = true)
   267     {
   268       Node b = addNode();
   269       nodes[b.id].first_out=nodes[n.id].first_out;
   270       nodes[n.id].first_out=-1;
   271       for(int i=nodes[b.id].first_out;i!=-1;i++) edges[i].source=b.id;
   272       if(connect) addEdge(n,b);
   273       return b;
   274     }
   275 
   276   public:
   277     
   278     class Snapshot;
   279 
   280   protected:
   281 
   282     void restoreSnapshot(const Snapshot &s)
   283     {
   284       while(s.edge_num<edges.size()) {
   285         Edge edge = edgeFromId(edges.size()-1);
   286 	Parent::getNotifier(Edge()).erase(edge);
   287 	nodes[edges.back().source].first_out=edges.back().next_out;
   288 	nodes[edges.back().target].first_in=edges.back().next_in;
   289 	edges.pop_back();
   290       }
   291       while(s.node_num<nodes.size()) {
   292         Node node = nodeFromId(nodes.size()-1);
   293 	Parent::getNotifier(Node()).erase(node);
   294 	nodes.pop_back();
   295       }
   296     }    
   297 
   298   public:
   299 
   300     ///Class to make a snapshot of the graph and to restrore to it later.
   301 
   302     ///Class to make a snapshot of the graph and to restrore to it later.
   303     ///
   304     ///The newly added nodes and edges can be removed using the
   305     ///restore() function.
   306     ///\note After you restore a state, you cannot restore
   307     ///a later state, in other word you cannot add again the edges deleted
   308     ///by restore() using another one Snapshot instance.
   309     ///
   310     ///\warning If you do not use correctly the snapshot that can cause
   311     ///either broken program, invalid state of the graph, valid but
   312     ///not the restored graph or no change. Because the runtime performance
   313     ///the validity of the snapshot is not stored.
   314     class Snapshot 
   315     {
   316       SmartGraph *g;
   317     protected:
   318       friend class SmartGraph;
   319       unsigned int node_num;
   320       unsigned int edge_num;
   321     public:
   322       ///Default constructor.
   323       
   324       ///Default constructor.
   325       ///To actually make a snapshot you must call save().
   326       ///
   327       Snapshot() : g(0) {}
   328       ///Constructor that immediately makes a snapshot
   329       
   330       ///This constructor immediately makes a snapshot of the graph.
   331       ///\param _g The graph we make a snapshot of.
   332       Snapshot(SmartGraph &_g) :g(&_g) {
   333 	node_num=g->nodes.size();
   334 	edge_num=g->edges.size();
   335       }
   336 
   337       ///Make a snapshot.
   338 
   339       ///Make a snapshot of the graph.
   340       ///
   341       ///This function can be called more than once. In case of a repeated
   342       ///call, the previous snapshot gets lost.
   343       ///\param _g The graph we make the snapshot of.
   344       void save(SmartGraph &_g) 
   345       {
   346 	g=&_g;
   347 	node_num=g->nodes.size();
   348 	edge_num=g->edges.size();
   349       }
   350 
   351       ///Undo the changes until a snapshot.
   352       
   353       ///Undo the changes until a snapshot created by save().
   354       ///
   355       ///\note After you restored a state, you cannot restore
   356       ///a later state, in other word you cannot add again the edges deleted
   357       ///by restore().
   358       void restore()
   359       {
   360 	g->restoreSnapshot(*this);
   361       }
   362     };
   363   };
   364 
   365 
   366   /**************** Undirected List Graph ****************/
   367 
   368   typedef UGraphExtender<UndirGraphExtender<SmartGraphBase> >
   369   ExtendedSmartUGraphBase;
   370 
   371   /// \ingroup graphs
   372   ///
   373   /// \brief A smart undirected graph class.
   374   ///
   375   /// This is a simple and fast undirected graph implementation.
   376   /// It is also quite memory efficient, but at the price
   377   /// that <b> it does support only limited (only stack-like)
   378   /// node and edge deletions</b>.
   379   /// Except from this it conforms to 
   380   /// the \ref concept::UGraph "UGraph concept".
   381   /// \sa concept::UGraph.
   382   ///
   383   /// \todo Snapshot hasn't been implemented yet.
   384   ///
   385   class SmartUGraph : public ExtendedSmartUGraphBase {
   386   private:
   387 
   388     ///SmartUGraph is \e not copy constructible. Use UGraphCopy() instead.
   389 
   390     ///SmartUGraph is \e not copy constructible. Use UGraphCopy() instead.
   391     ///
   392     SmartUGraph(const SmartUGraph &) : ExtendedSmartUGraphBase() {};
   393 
   394     ///\brief Assignment of SmartUGraph to another one is \e not allowed.
   395     ///Use UGraphCopy() instead.
   396 
   397     ///Assignment of SmartUGraph to another one is \e not allowed.
   398     ///Use UGraphCopy() instead.
   399     void operator=(const SmartUGraph &) {}
   400 
   401   public:
   402 
   403     typedef ExtendedSmartUGraphBase Parent;
   404 
   405     /// Constructor
   406     
   407     /// Constructor.
   408     ///
   409     SmartUGraph() {}
   410 
   411     ///Add a new node to the graph.
   412     
   413     /// \return the new node.
   414     ///
   415     Node addNode() { return Parent::addNode(); }
   416     
   417     ///Add a new undirected edge to the graph.
   418     
   419     ///Add a new undirected edge to the graph with node \c s
   420     ///and \c t.
   421     ///\return the new undirected edge.
   422     UEdge addEdge(const Node& s, const Node& t) { 
   423       return Parent::addEdge(s, t); 
   424     }
   425 
   426     ///Clear the graph.
   427     
   428     ///Erase all the nodes and edges from the graph.
   429     ///
   430     void clear() {
   431       Parent::clear();
   432     }
   433 
   434   public:
   435     
   436     class Snapshot;
   437 
   438   protected:
   439 
   440 
   441     void restoreSnapshot(const Snapshot &s)
   442     {
   443       while(s.edge_num<edges.size()) {
   444         UEdge edge = uEdgeFromId(edges.size()-1);
   445 	Parent::getNotifier(UEdge()).erase(edge);
   446         std::vector<Edge> dir;
   447         dir.push_back(Parent::direct(edge, true));
   448         dir.push_back(Parent::direct(edge, false));
   449 	Parent::getNotifier(Edge()).erase(dir);
   450 	nodes[edges.back().source].first_out=edges.back().next_out;
   451 	nodes[edges.back().target].first_in=edges.back().next_in;
   452 	edges.pop_back();
   453       }
   454       while(s.node_num<nodes.size()) {
   455         Node node = nodeFromId(nodes.size()-1);
   456 	Parent::getNotifier(Node()).erase(node);
   457 	nodes.pop_back();
   458       }
   459     }    
   460 
   461   public:
   462 
   463     ///Class to make a snapshot of the graph and to restrore to it later.
   464 
   465     ///Class to make a snapshot of the graph and to restrore to it later.
   466     ///
   467     ///The newly added nodes and edges can be removed using the
   468     ///restore() function.
   469     ///
   470     ///\note After you restore a state, you cannot restore
   471     ///a later state, in other word you cannot add again the edges deleted
   472     ///by restore() using another one Snapshot instance.
   473     ///
   474     ///\warning If you do not use correctly the snapshot that can cause
   475     ///either broken program, invalid state of the graph, valid but
   476     ///not the restored graph or no change. Because the runtime performance
   477     ///the validity of the snapshot is not stored.
   478     class Snapshot 
   479     {
   480       SmartUGraph *g;
   481     protected:
   482       friend class SmartUGraph;
   483       unsigned int node_num;
   484       unsigned int edge_num;
   485     public:
   486       ///Default constructor.
   487       
   488       ///Default constructor.
   489       ///To actually make a snapshot you must call save().
   490       ///
   491       Snapshot() : g(0) {}
   492       ///Constructor that immediately makes a snapshot
   493       
   494       ///This constructor immediately makes a snapshot of the graph.
   495       ///\param _g The graph we make a snapshot of.
   496       Snapshot(SmartUGraph &_g) :g(&_g) {
   497 	node_num=g->nodes.size();
   498 	edge_num=g->edges.size();
   499       }
   500 
   501       ///Make a snapshot.
   502 
   503       ///Make a snapshot of the graph.
   504       ///
   505       ///This function can be called more than once. In case of a repeated
   506       ///call, the previous snapshot gets lost.
   507       ///\param _g The graph we make the snapshot of.
   508       void save(SmartUGraph &_g) 
   509       {
   510 	g=&_g;
   511 	node_num=g->nodes.size();
   512 	edge_num=g->edges.size();
   513       }
   514 
   515       ///Undo the changes until a snapshot.
   516       
   517       ///Undo the changes until a snapshot created by save().
   518       ///
   519       ///\note After you restored a state, you cannot restore
   520       ///a later state, in other word you cannot add again the edges deleted
   521       ///by restore().
   522       void restore()
   523       {
   524 	g->restoreSnapshot(*this);
   525       }
   526     };
   527   };
   528 
   529 
   530   class SmartBpUGraphBase {
   531   public:
   532 
   533     class NodeSetError : public LogicError {
   534     public:
   535       virtual const char* what() const throw() { 
   536 	return "lemon::SmartBpUGraph::NodeSetError";
   537       }
   538     };
   539 
   540   protected:
   541 
   542     struct NodeT {
   543       int first;
   544       NodeT() {}
   545       NodeT(int _first) : first(_first) {}
   546     };
   547 
   548     struct UEdgeT {
   549       int aNode, next_out;
   550       int bNode, next_in;
   551     };
   552 
   553     std::vector<NodeT> aNodes;
   554     std::vector<NodeT> bNodes;
   555 
   556     std::vector<UEdgeT> edges;
   557 
   558   public:
   559   
   560     class Node {
   561       friend class SmartBpUGraphBase;
   562     protected:
   563       int id;
   564 
   565       explicit Node(int _id) : id(_id) {}
   566     public:
   567       Node() {}
   568       Node(Invalid) : id(-1) {}
   569       bool operator==(const Node i) const {return id==i.id;}
   570       bool operator!=(const Node i) const {return id!=i.id;}
   571       bool operator<(const Node i) const {return id<i.id;}
   572     };
   573 
   574     class UEdge {
   575       friend class SmartBpUGraphBase;
   576     protected:
   577       int id;
   578 
   579       UEdge(int _id) : id(_id) {}
   580     public:
   581       UEdge() {}
   582       UEdge(Invalid) : id(-1) {}
   583       bool operator==(const UEdge i) const {return id==i.id;}
   584       bool operator!=(const UEdge i) const {return id!=i.id;}
   585       bool operator<(const UEdge i) const {return id<i.id;}
   586     };
   587 
   588     void firstANode(Node& node) const {
   589       node.id = 2 * aNodes.size() - 2;
   590       if (node.id < 0) node.id = -1; 
   591     }
   592     void nextANode(Node& node) const {
   593       node.id -= 2;
   594       if (node.id < 0) node.id = -1; 
   595     }
   596 
   597     void firstBNode(Node& node) const {
   598       node.id = 2 * bNodes.size() - 1;
   599     }
   600     void nextBNode(Node& node) const {
   601       node.id -= 2;
   602     }
   603 
   604     void first(Node& node) const {
   605       if (aNodes.size() > 0) {
   606 	node.id = 2 * aNodes.size() - 2;
   607       } else {
   608 	node.id = 2 * bNodes.size() - 1;
   609       }
   610     }
   611     void next(Node& node) const {
   612       node.id -= 2;
   613       if (node.id == -2) {
   614 	node.id = 2 * bNodes.size() - 1;
   615       }
   616     }
   617   
   618     void first(UEdge& edge) const {
   619       edge.id = edges.size() - 1;
   620     }
   621     void next(UEdge& edge) const {
   622       --edge.id;
   623     }
   624 
   625     void firstFromANode(UEdge& edge, const Node& node) const {
   626       LEMON_ASSERT((node.id & 1) == 0, NodeSetError());
   627       edge.id = aNodes[node.id >> 1].first;
   628     }
   629     void nextFromANode(UEdge& edge) const {
   630       edge.id = edges[edge.id].next_out;
   631     }
   632 
   633     void firstFromBNode(UEdge& edge, const Node& node) const {
   634       LEMON_ASSERT((node.id & 1) == 1, NodeSetError());
   635       edge.id = bNodes[node.id >> 1].first;
   636     }
   637     void nextFromBNode(UEdge& edge) const {
   638       edge.id = edges[edge.id].next_in;
   639     }
   640 
   641     static int id(const Node& node) {
   642       return node.id;
   643     }
   644     static Node nodeFromId(int id) {
   645       return Node(id);
   646     }
   647     int maxNodeId() const {
   648       return aNodes.size() > bNodes.size() ?
   649 	aNodes.size() * 2 - 2 : bNodes.size() * 2 - 1;
   650     }
   651   
   652     static int id(const UEdge& edge) {
   653       return edge.id;
   654     }
   655     static UEdge uEdgeFromId(int id) {
   656       return UEdge(id);
   657     }
   658     int maxUEdgeId() const {
   659       return edges.size();
   660     }
   661   
   662     static int aNodeId(const Node& node) {
   663       return node.id >> 1;
   664     }
   665     static Node nodeFromANodeId(int id) {
   666       return Node(id << 1);
   667     }
   668     int maxANodeId() const {
   669       return aNodes.size();
   670     }
   671 
   672     static int bNodeId(const Node& node) {
   673       return node.id >> 1;
   674     }
   675     static Node nodeFromBNodeId(int id) {
   676       return Node((id << 1) + 1);
   677     }
   678     int maxBNodeId() const {
   679       return bNodes.size();
   680     }
   681 
   682     Node aNode(const UEdge& edge) const {
   683       return Node(edges[edge.id].aNode);
   684     }
   685     Node bNode(const UEdge& edge) const {
   686       return Node(edges[edge.id].bNode);
   687     }
   688 
   689     static bool aNode(const Node& node) {
   690       return (node.id & 1) == 0;
   691     }
   692 
   693     static bool bNode(const Node& node) {
   694       return (node.id & 1) == 1;
   695     }
   696 
   697     Node addANode() {
   698       NodeT nodeT;
   699       nodeT.first = -1;
   700       aNodes.push_back(nodeT);
   701       return Node(aNodes.size() * 2 - 2);
   702     }
   703 
   704     Node addBNode() {
   705       NodeT nodeT;
   706       nodeT.first = -1;
   707       bNodes.push_back(nodeT);
   708       return Node(bNodes.size() * 2 - 1);
   709     }
   710 
   711     UEdge addEdge(const Node& source, const Node& target) {
   712       LEMON_ASSERT(((source.id ^ target.id) & 1) == 1, NodeSetError());
   713       UEdgeT edgeT;
   714       if ((source.id & 1) == 0) {
   715 	edgeT.aNode = source.id;
   716 	edgeT.bNode = target.id;
   717       } else {
   718 	edgeT.aNode = target.id;
   719 	edgeT.bNode = source.id;
   720       }
   721       edgeT.next_out = aNodes[edgeT.aNode >> 1].first;
   722       aNodes[edgeT.aNode >> 1].first = edges.size();
   723       edgeT.next_in = bNodes[edgeT.bNode >> 1].first;
   724       bNodes[edgeT.bNode >> 1].first = edges.size();
   725       edges.push_back(edgeT);
   726       return UEdge(edges.size() - 1);
   727     }
   728 
   729     void clear() {
   730       aNodes.clear();
   731       bNodes.clear();
   732       edges.clear();
   733     }
   734 
   735     typedef True NodeNumTag;
   736     int nodeNum() const { return aNodes.size() + bNodes.size(); }
   737     int aNodeNum() const { return aNodes.size(); }
   738     int bNodeNum() const { return bNodes.size(); }
   739 
   740     typedef True EdgeNumTag;
   741     int uEdgeNum() const { return edges.size(); }
   742 
   743   };
   744 
   745 
   746   typedef BpUGraphExtender<BidirBpUGraphExtender<SmartBpUGraphBase> >
   747   ExtendedSmartBpUGraphBase;
   748 
   749   /// \ingroup graphs
   750   ///
   751   /// \brief A smart bipartite undirected graph class.
   752   ///
   753   /// This is a simple and fast bipartite undirected graph implementation.
   754   /// It is also quite memory efficient, but at the price
   755   /// that <b> it does not support node and edge deletions</b>.
   756   /// Except from this it conforms to 
   757   /// the \ref concept::BpUGraph "BpUGraph concept".
   758   /// \sa concept::BpUGraph.
   759   ///
   760   class SmartBpUGraph : public ExtendedSmartBpUGraphBase {
   761   private:
   762 
   763     /// \brief SmartBpUGraph is \e not copy constructible.
   764     ///
   765     ///SmartBpUGraph is \e not copy constructible.
   766     SmartBpUGraph(const SmartBpUGraph &) : ExtendedSmartBpUGraphBase() {};
   767 
   768     /// \brief Assignment of SmartBpUGraph to another one is \e not
   769     /// allowed.
   770     ///
   771     /// Assignment of SmartBpUGraph to another one is \e not allowed.
   772     void operator=(const SmartBpUGraph &) {}
   773 
   774   public:
   775 
   776     typedef ExtendedSmartBpUGraphBase Parent;
   777 
   778     ///Constructor
   779     
   780     ///Constructor.
   781     ///
   782     SmartBpUGraph() : ExtendedSmartBpUGraphBase() {}
   783 
   784     ///Add a new ANode to the graph.
   785     
   786     /// \return the new node.
   787     ///
   788     Node addANode() { return Parent::addANode(); }
   789 
   790     ///Add a new BNode to the graph.
   791     
   792     /// \return the new node.
   793     ///
   794     Node addBNode() { return Parent::addBNode(); }
   795     
   796     ///Add a new undirected edge to the graph.
   797     
   798     ///Add a new undirected edge to the graph with node \c s
   799     ///and \c t.
   800     ///\return the new undirected edge.
   801     UEdge addEdge(const Node& s, const Node& t) { 
   802       return Parent::addEdge(s, t); 
   803     }
   804 
   805     ///Clear the graph.
   806     
   807     ///Erase all the nodes and edges from the graph.
   808     ///
   809     void clear() {
   810       Parent::clear();
   811     }
   812     
   813   public:
   814 
   815     class Snapshot;
   816 
   817   protected:
   818     
   819     void restoreSnapshot(const Snapshot &s)
   820     {
   821       while(s.edge_num<edges.size()) {
   822         UEdge edge = uEdgeFromId(edges.size()-1);
   823 	Parent::getNotifier(UEdge()).erase(edge);
   824         std::vector<Edge> dir;
   825         dir.push_back(Parent::direct(edge, true));
   826         dir.push_back(Parent::direct(edge, false));
   827 	Parent::getNotifier(Edge()).erase(dir);
   828 	aNodes[edges.back().aNode >> 1].first=edges.back().next_out;
   829 	bNodes[edges.back().bNode >> 1].first=edges.back().next_in;
   830 	edges.pop_back();
   831       }
   832       while(s.anode_num<aNodes.size()) {
   833         Node node = nodeFromANodeId(aNodes.size() - 1);
   834 	Parent::getNotifier(ANode()).erase(node);
   835 	Parent::getNotifier(Node()).erase(node);
   836 	aNodes.pop_back();
   837       }
   838       while(s.bnode_num<bNodes.size()) {
   839         Node node = nodeFromBNodeId(bNodes.size() - 1);
   840 	Parent::getNotifier(BNode()).erase(node);
   841 	Parent::getNotifier(Node()).erase(node);
   842 	bNodes.pop_back();
   843       }
   844     }    
   845 
   846   public:
   847 
   848     ///Class to make a snapshot of the graph and to restrore to it later.
   849 
   850     ///Class to make a snapshot of the graph and to restrore to it later.
   851     ///
   852     ///The newly added nodes and edges can be removed using the
   853     ///restore() function.
   854     ///
   855     ///\note After you restore a state, you cannot restore
   856     ///a later state, in other word you cannot add again the edges deleted
   857     ///by restore() using another one Snapshot instance.
   858     ///
   859     ///\warning If you do not use correctly the snapshot that can cause
   860     ///either broken program, invalid state of the graph, valid but
   861     ///not the restored graph or no change. Because the runtime performance
   862     ///the validity of the snapshot is not stored.
   863     class Snapshot 
   864     {
   865       SmartBpUGraph *g;
   866     protected:
   867       friend class SmartBpUGraph;
   868       unsigned int anode_num;
   869       unsigned int bnode_num;
   870       unsigned int edge_num;
   871     public:
   872       ///Default constructor.
   873       
   874       ///Default constructor.
   875       ///To actually make a snapshot you must call save().
   876       ///
   877       Snapshot() : g(0) {}
   878 
   879       ///Constructor that immediately makes a snapshot
   880       
   881       ///This constructor immediately makes a snapshot of the graph.
   882       ///\param _g The graph we make a snapshot of.
   883       Snapshot(SmartBpUGraph &_g) : g(&_g) {
   884 	anode_num=g->aNodes.size();
   885 	bnode_num=g->bNodes.size();
   886 	edge_num=g->edges.size();
   887       }
   888 
   889       ///Make a snapshot.
   890 
   891       ///Make a snapshot of the graph.
   892       ///
   893       ///This function can be called more than once. In case of a repeated
   894       ///call, the previous snapshot gets lost.
   895       ///\param _g The graph we make the snapshot of.
   896       void save(SmartBpUGraph &_g) 
   897       {
   898 	g=&_g;
   899 	anode_num=g->aNodes.size();
   900 	bnode_num=g->bNodes.size();
   901 	edge_num=g->edges.size();
   902       }
   903 
   904       ///Undo the changes until a snapshot.
   905       
   906       ///Undo the changes until a snapshot created by save().
   907       ///
   908       ///\note After you restored a state, you cannot restore
   909       ///a later state, in other word you cannot add again the edges deleted
   910       ///by restore().
   911       void restore()
   912       {
   913 	g->restoreSnapshot(*this);
   914       }
   915     };
   916   };
   917 
   918   
   919   /// @}  
   920 } //namespace lemon
   921 
   922 
   923 #endif //LEMON_SMART_GRAPH_H