lemon/list_graph.h
author deba
Wed, 28 Jun 2006 15:06:24 +0000
changeset 2111 ea1fa1bc3f6d
parent 2107 e1055232c670
child 2114 677ea6c8169a
permissions -rw-r--r--
Removing concepts for extendable and erasable graphs
Renaming StaticGraph to Graph
     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_LIST_GRAPH_H
    20 #define LEMON_LIST_GRAPH_H
    21 
    22 ///\ingroup graphs
    23 ///\file
    24 ///\brief ListGraph, ListUGraph classes.
    25 
    26 #include <lemon/bits/base_extender.h>
    27 #include <lemon/bits/graph_extender.h>
    28 
    29 #include <lemon/error.h>
    30 
    31 #include <vector>
    32 #include <list>
    33 
    34 namespace lemon {
    35 
    36   class ListGraphBase {
    37 
    38   protected:
    39     struct NodeT {
    40       int first_in, first_out;
    41       int prev, next;
    42     };
    43  
    44     struct EdgeT {
    45       int target, source;
    46       int prev_in, prev_out;
    47       int next_in, next_out;
    48     };
    49 
    50     std::vector<NodeT> nodes;
    51 
    52     int first_node;
    53 
    54     int first_free_node;
    55 
    56     std::vector<EdgeT> edges;
    57 
    58     int first_free_edge;
    59     
    60   public:
    61     
    62     typedef ListGraphBase Graph;
    63     
    64     class Node {
    65       friend class ListGraphBase;
    66     protected:
    67 
    68       int id;
    69       explicit Node(int pid) { id = pid;}
    70 
    71     public:
    72       Node() {}
    73       Node (Invalid) { id = -1; }
    74       bool operator==(const Node& node) const {return id == node.id;}
    75       bool operator!=(const Node& node) const {return id != node.id;}
    76       bool operator<(const Node& node) const {return id < node.id;}
    77     };
    78 
    79     class Edge {
    80       friend class ListGraphBase;
    81     protected:
    82 
    83       int id;
    84       explicit Edge(int pid) { id = pid;}
    85 
    86     public:
    87       Edge() {}
    88       Edge (Invalid) { id = -1; }
    89       bool operator==(const Edge& edge) const {return id == edge.id;}
    90       bool operator!=(const Edge& edge) const {return id != edge.id;}
    91       bool operator<(const Edge& edge) const {return id < edge.id;}
    92     };
    93 
    94 
    95 
    96     ListGraphBase()
    97       : nodes(), first_node(-1),
    98 	first_free_node(-1), edges(), first_free_edge(-1) {}
    99 
   100     
   101     /// Maximum node ID.
   102     
   103     /// Maximum node ID.
   104     ///\sa id(Node)
   105     int maxNodeId() const { return nodes.size()-1; } 
   106 
   107     /// Maximum edge ID.
   108     
   109     /// Maximum edge ID.
   110     ///\sa id(Edge)
   111     int maxEdgeId() const { return edges.size()-1; }
   112 
   113     Node source(Edge e) const { return Node(edges[e.id].source); }
   114     Node target(Edge e) const { return Node(edges[e.id].target); }
   115 
   116 
   117     void first(Node& node) const { 
   118       node.id = first_node;
   119     }
   120 
   121     void next(Node& node) const {
   122       node.id = nodes[node.id].next;
   123     }
   124 
   125 
   126     void first(Edge& e) const { 
   127       int n;
   128       for(n = first_node; 
   129 	  n!=-1 && nodes[n].first_in == -1; 
   130 	  n = nodes[n].next);
   131       e.id = (n == -1) ? -1 : nodes[n].first_in;
   132     }
   133 
   134     void next(Edge& edge) const {
   135       if (edges[edge.id].next_in != -1) {
   136 	edge.id = edges[edge.id].next_in;
   137       } else {
   138 	int n;
   139 	for(n = nodes[edges[edge.id].target].next;
   140 	  n!=-1 && nodes[n].first_in == -1; 
   141 	  n = nodes[n].next);
   142 	edge.id = (n == -1) ? -1 : nodes[n].first_in;
   143       }      
   144     }
   145 
   146     void firstOut(Edge &e, const Node& v) const {
   147       e.id = nodes[v.id].first_out;
   148     }
   149     void nextOut(Edge &e) const {
   150       e.id=edges[e.id].next_out;
   151     }
   152 
   153     void firstIn(Edge &e, const Node& v) const {
   154       e.id = nodes[v.id].first_in;
   155     }
   156     void nextIn(Edge &e) const {
   157       e.id=edges[e.id].next_in;
   158     }
   159 
   160     
   161     static int id(Node v) { return v.id; }
   162     static int id(Edge e) { return e.id; }
   163 
   164     static Node nodeFromId(int id) { return Node(id);}
   165     static Edge edgeFromId(int id) { return Edge(id);}
   166 
   167     /// Adds a new node to the graph.
   168 
   169     /// \warning It adds the new node to the front of the list.
   170     /// (i.e. the lastly added node becomes the first.)
   171     Node addNode() {     
   172       int n;
   173       
   174       if(first_free_node==-1) {
   175 	n = nodes.size();
   176 	nodes.push_back(NodeT());
   177       } else {
   178 	n = first_free_node;
   179 	first_free_node = nodes[n].next;
   180       }
   181       
   182       nodes[n].next = first_node;
   183       if(first_node != -1) nodes[first_node].prev = n;
   184       first_node = n;
   185       nodes[n].prev = -1;
   186       
   187       nodes[n].first_in = nodes[n].first_out = -1;
   188       
   189       return Node(n);
   190     }
   191     
   192     Edge addEdge(Node u, Node v) {
   193       int n;      
   194 
   195       if (first_free_edge == -1) {
   196 	n = edges.size();
   197 	edges.push_back(EdgeT());
   198       } else {
   199 	n = first_free_edge;
   200 	first_free_edge = edges[n].next_in;
   201       }
   202       
   203       edges[n].source = u.id; 
   204       edges[n].target = v.id;
   205 
   206       edges[n].next_out = nodes[u.id].first_out;
   207       if(nodes[u.id].first_out != -1) {
   208 	edges[nodes[u.id].first_out].prev_out = n;
   209       }
   210       
   211       edges[n].next_in = nodes[v.id].first_in;
   212       if(nodes[v.id].first_in != -1) {
   213 	edges[nodes[v.id].first_in].prev_in = n;
   214       }
   215       
   216       edges[n].prev_in = edges[n].prev_out = -1;
   217 	
   218       nodes[u.id].first_out = nodes[v.id].first_in = n;
   219 
   220       return Edge(n);
   221     }
   222     
   223     void erase(const Node& node) {
   224       int n = node.id;
   225       
   226       if(nodes[n].next != -1) {
   227 	nodes[nodes[n].next].prev = nodes[n].prev;
   228       }
   229       
   230       if(nodes[n].prev != -1) {
   231 	nodes[nodes[n].prev].next = nodes[n].next;
   232       } else {
   233 	first_node = nodes[n].next;
   234       }
   235       
   236       nodes[n].next = first_free_node;
   237       first_free_node = n;
   238 
   239     }
   240     
   241     void erase(const Edge& edge) {
   242       int n = edge.id;
   243       
   244       if(edges[n].next_in!=-1) {
   245 	edges[edges[n].next_in].prev_in = edges[n].prev_in;
   246       }
   247 
   248       if(edges[n].prev_in!=-1) {
   249 	edges[edges[n].prev_in].next_in = edges[n].next_in;
   250       } else {
   251 	nodes[edges[n].target].first_in = edges[n].next_in;
   252       }
   253 
   254       
   255       if(edges[n].next_out!=-1) {
   256 	edges[edges[n].next_out].prev_out = edges[n].prev_out;
   257       } 
   258 
   259       if(edges[n].prev_out!=-1) {
   260 	edges[edges[n].prev_out].next_out = edges[n].next_out;
   261       } else {
   262 	nodes[edges[n].source].first_out = edges[n].next_out;
   263       }
   264       
   265       edges[n].next_in = first_free_edge;
   266       first_free_edge = n;      
   267 
   268     }
   269 
   270     void clear() {
   271       edges.clear();
   272       nodes.clear();
   273       first_node = first_free_node = first_free_edge = -1;
   274     }
   275 
   276   protected:
   277     void changeTarget(Edge e, Node n) 
   278     {
   279       if(edges[e.id].next_in != -1)
   280 	edges[edges[e.id].next_in].prev_in = edges[e.id].prev_in;
   281       if(edges[e.id].prev_in != -1)
   282 	edges[edges[e.id].prev_in].next_in = edges[e.id].next_in;
   283       else nodes[edges[e.id].target].first_in = edges[e.id].next_in;
   284       if (nodes[n.id].first_in != -1) {
   285 	edges[nodes[n.id].first_in].prev_in = e.id;
   286       }
   287       edges[e.id].target = n.id;
   288       edges[e.id].prev_in = -1;
   289       edges[e.id].next_in = nodes[n.id].first_in;
   290       nodes[n.id].first_in = e.id;
   291     }
   292     void changeSource(Edge e, Node n) 
   293     {
   294       if(edges[e.id].next_out != -1)
   295 	edges[edges[e.id].next_out].prev_out = edges[e.id].prev_out;
   296       if(edges[e.id].prev_out != -1)
   297 	edges[edges[e.id].prev_out].next_out = edges[e.id].next_out;
   298       else nodes[edges[e.id].source].first_out = edges[e.id].next_out;
   299       if (nodes[n.id].first_out != -1) {
   300 	edges[nodes[n.id].first_out].prev_out = e.id;
   301       }
   302       edges[e.id].source = n.id;
   303       edges[e.id].prev_out = -1;
   304       edges[e.id].next_out = nodes[n.id].first_out;
   305       nodes[n.id].first_out = e.id;
   306     }
   307 
   308   };
   309 
   310   typedef GraphExtender<ListGraphBase> ExtendedListGraphBase;
   311 
   312   /// \addtogroup graphs
   313   /// @{
   314 
   315   ///A list graph class.
   316 
   317   ///This is a simple and fast erasable graph implementation.
   318   ///
   319   ///It conforms to the \ref concept::Graph "Graph" concept and it
   320   ///also provides several additional useful extra functionalities.
   321   ///The most of the member functions and nested classes are
   322   ///documented only in the concept class.
   323   ///\sa concept::Graph.
   324 
   325   class ListGraph : public ExtendedListGraphBase {
   326   public:
   327 
   328     typedef ExtendedListGraphBase Parent;
   329 
   330     ///Add a new node to the graph.
   331     
   332     /// \return the new node.
   333     ///
   334     Node addNode() { return Parent::addNode(); }
   335 
   336     ///Add a new edge to the graph.
   337     
   338     ///Add a new edge to the graph with source node \c s
   339     ///and target node \c t.
   340     ///\return the new edge.
   341     Edge addEdge(const Node& s, const Node& t) { 
   342       return Parent::addEdge(s, t); 
   343     }
   344 
   345     /// Changes the target of \c e to \c n
   346 
   347     /// Changes the target of \c e to \c n
   348     ///
   349     ///\note The <tt>Edge</tt>s and <tt>OutEdge</tt>s
   350     ///referencing the changed edge remain
   351     ///valid. However <tt>InEdge</tt>s are invalidated.
   352     void changeTarget(Edge e, Node n) { 
   353       Parent::changeTarget(e,n); 
   354     }
   355     /// Changes the source of \c e to \c n
   356 
   357     /// Changes the source of \c e to \c n
   358     ///
   359     ///\note The <tt>Edge</tt>s and <tt>InEdge</tt>s
   360     ///referencing the changed edge remain
   361     ///valid. However <tt>OutEdge</tt>s are invalidated.
   362     void changeSource(Edge e, Node n) { 
   363       Parent::changeSource(e,n);
   364     }
   365 
   366     /// Invert the direction of an edge.
   367 
   368     ///\note The <tt>Edge</tt>s
   369     ///referencing the changed edge remain
   370     ///valid. However <tt>OutEdge</tt>s  and <tt>InEdge</tt>s are invalidated.
   371     void reverseEdge(Edge e) {
   372       Node t=target(e);
   373       changeTarget(e,source(e));
   374       changeSource(e,t);
   375     }
   376 
   377     /// \brief Using this it is possible to avoid the superfluous memory
   378     /// allocation.
   379 
   380     ///Using this it is possible to avoid the superfluous memory
   381     ///allocation: if you know that the graph you want to build will
   382     ///contain at least 10 million nodes then it is worth to reserve
   383     ///space for this amount before starting to build the graph.
   384     void reserveNode(int n) { nodes.reserve(n); };
   385 
   386     /// \brief Using this it is possible to avoid the superfluous memory
   387     /// allocation.
   388 
   389     ///Using this it is possible to avoid the superfluous memory
   390     ///allocation: see the \ref reserveNode function.
   391     void reserveEdge(int n) { edges.reserve(n); };
   392 
   393 
   394     ///Contract two nodes.
   395 
   396     ///This function contracts two nodes.
   397     ///
   398     ///Node \p b will be removed but instead of deleting
   399     ///incident edges, they will be joined to \p a.
   400     ///The last parameter \p r controls whether to remove loops. \c true
   401     ///means that loops will be removed.
   402     ///
   403     ///\note The <tt>Edge</tt>s
   404     ///referencing a moved edge remain
   405     ///valid. However <tt>InEdge</tt>s and <tt>OutEdge</tt>s
   406     ///may be invalidated.
   407     void contract(Node a, Node b, bool r = true) 
   408     {
   409       for(OutEdgeIt e(*this,b);e!=INVALID;) {
   410 	OutEdgeIt f=e;
   411 	++f;
   412 	if(r && target(e)==a) erase(e);
   413 	else changeSource(e,a);
   414 	e=f;
   415       }
   416       for(InEdgeIt e(*this,b);e!=INVALID;) {
   417 	InEdgeIt f=e;
   418 	++f;
   419 	if(r && source(e)==a) erase(e);
   420 	else changeTarget(e,a);
   421 	e=f;
   422       }
   423       erase(b);
   424     }
   425 
   426     ///Split a node.
   427 
   428     ///This function splits a node. First a new node is added to the graph,
   429     ///then the source of each outgoing edge of \c n is moved to this new node.
   430     ///If \c connect is \c true (this is the default value), then a new edge
   431     ///from \c n to the newly created node is also added.
   432     ///\return The newly created node.
   433     ///
   434     ///\note The <tt>Edge</tt>s
   435     ///referencing a moved edge remain
   436     ///valid. However <tt>InEdge</tt>s and <tt>OutEdge</tt>s
   437     ///may be invalidated.
   438     ///\warning This functionality cannot be used together with the Snapshot
   439     ///feature.
   440     ///\todo It could be implemented in a bit faster way.
   441     Node split(Node n, bool connect = true) 
   442     {
   443       Node b = addNode();
   444       for(OutEdgeIt e(*this,n);e!=INVALID;) {
   445  	OutEdgeIt f=e;
   446 	++f;
   447 	changeSource(e,b);
   448 	e=f;
   449       }
   450       if(connect) addEdge(n,b);
   451       return b;
   452     }
   453       
   454     ///Split an edge.
   455 
   456     ///This function splits an edge. First a new node \c b is added to
   457     ///the graph, then the original edge is re-targeted to \c
   458     ///b. Finally an edge from \c b to the original target is added.
   459     ///\return The newly created node.  
   460     ///\warning This functionality
   461     ///cannot be used together with the Snapshot feature.
   462     Node split(Edge e) 
   463     {
   464       Node b = addNode();
   465       addEdge(b,target(e));
   466       changeTarget(e,b);
   467       return b;
   468     }
   469       
   470     ///Class to make a snapshot of the graph and to restore  it later.
   471 
   472     ///Class to make a snapshot of the graph and to restore  it later.
   473     ///
   474     ///The newly added nodes and edges can be removed using the
   475     ///restore() function.
   476     ///
   477     ///\warning Edge and node deletions cannot be restored.
   478     ///\warning Snapshots cannot be nested.
   479     class Snapshot : protected Parent::NodeNotifier::ObserverBase,
   480 		     protected Parent::EdgeNotifier::ObserverBase
   481     {
   482     public:
   483       
   484       class UnsupportedOperation : public LogicError {
   485       public:
   486 	virtual const char* exceptionName() const {
   487 	  return "lemon::ListGraph::Snapshot::UnsupportedOperation";
   488 	}
   489       };
   490             
   491 
   492     protected:
   493       
   494       ListGraph *g;
   495       std::list<Node> added_nodes;
   496       std::list<Edge> added_edges;
   497       
   498       bool active;
   499       virtual void add(const Node& n) {
   500 	added_nodes.push_back(n);
   501       };
   502       virtual void erase(const Node&) 
   503       {
   504 	throw UnsupportedOperation();
   505       }
   506       virtual void add(const Edge& n) {
   507 	added_edges.push_back(n);
   508       };
   509       virtual void erase(const Edge&) 
   510       {
   511 	throw UnsupportedOperation();
   512       }
   513 
   514       ///\bug What is this used for?
   515       ///
   516       virtual void build() {}
   517       ///\bug What is this used for?
   518       ///
   519       virtual void clear() {}
   520 
   521       void regist(ListGraph &_g) {
   522 	g=&_g;
   523 	Parent::NodeNotifier::ObserverBase::attach(g->getNotifier(Node()));
   524 	Parent::EdgeNotifier::ObserverBase::attach(g->getNotifier(Edge()));
   525       }
   526             
   527       void deregist() {
   528 	Parent::NodeNotifier::ObserverBase::detach();
   529 	Parent::EdgeNotifier::ObserverBase::detach();
   530 	g=0;
   531       }
   532 
   533     public:
   534       ///Default constructur.
   535       
   536       ///Default constructur.
   537       ///To actually make a snapshot you must call save().
   538       ///
   539       Snapshot() : g(0) {}
   540       ///Constructor that immediately makes a snapshot.
   541       
   542       ///This constructor immediately makes a snapshot of the graph.
   543       ///\param _g The graph we make a snapshot of.
   544       Snapshot(ListGraph &_g) {
   545 	regist(_g);
   546       }
   547       ///\bug Is it necessary?
   548       ///
   549       ~Snapshot() 
   550       {
   551 	if(g) deregist();
   552       }
   553       
   554       ///Make a snapshot.
   555 
   556       ///Make a snapshot of the graph.
   557       ///
   558       ///This function can be called more than once. In case of a repeated
   559       ///call, the previous snapshot gets lost.
   560       ///\param _g The graph we make the snapshot of.
   561       void save(ListGraph &_g) 
   562       {
   563 	if(g!=&_g) {
   564 	  if(g) deregist();
   565 	  regist(_g);
   566 	}
   567 	added_nodes.clear();
   568 	added_edges.clear();
   569       }
   570       
   571     ///Undo the changes until the last snapshot.
   572 
   573     ///Undo the changes until last snapshot created by save().
   574     ///
   575     ///\todo This function might be called undo().
   576       void restore() {
   577 	ListGraph &old_g=*g;
   578 	deregist();
   579 	while(!added_edges.empty()) {
   580 	  old_g.erase(added_edges.front());
   581 	  added_edges.pop_front();
   582 	}
   583  	while(!added_nodes.empty()) {
   584 	  old_g.erase(added_nodes.front());
   585 	  added_nodes.pop_front();
   586 	}
   587       }
   588     };
   589     
   590   };
   591 
   592   ///@}
   593 
   594   /**************** Undirected List Graph ****************/
   595 
   596   typedef UGraphExtender<UndirGraphExtender<ListGraphBase> > 
   597   ExtendedListUGraphBase;
   598 
   599   /// \addtogroup graphs
   600   /// @{
   601 
   602   ///An undirected list graph class.
   603 
   604   ///This is a simple and fast erasable undirected graph implementation.
   605   ///
   606   ///It conforms to the
   607   ///\ref concept::UGraph "UGraph" concept.
   608   ///
   609   ///\sa concept::UGraph.
   610   ///
   611   ///\todo Snapshot, reverseEdge(), changeTarget(), changeSource(), contract()
   612   ///haven't been implemented yet.
   613   ///
   614   class ListUGraph : public ExtendedListUGraphBase {
   615   public:
   616     typedef ExtendedListUGraphBase Parent;
   617     /// \brief Add a new node to the graph.
   618     ///
   619     /// \return the new node.
   620     ///
   621     Node addNode() { return Parent::addNode(); }
   622 
   623     /// \brief Add a new edge to the graph.
   624     ///
   625     /// Add a new edge to the graph with source node \c s
   626     /// and target node \c t.
   627     /// \return the new undirected edge.
   628     UEdge addEdge(const Node& s, const Node& t) { 
   629       return Parent::addEdge(s, t); 
   630     }
   631     /// \brief Changes the target of \c e to \c n
   632     ///
   633     /// Changes the target of \c e to \c n
   634     ///
   635     /// \note The <tt>Edge</tt>'s and <tt>OutEdge</tt>'s
   636     /// referencing the changed edge remain
   637     /// valid. However <tt>InEdge</tt>'s are invalidated.
   638     void changeTarget(UEdge e, Node n) { 
   639       Parent::changeTarget(e,n); 
   640     }
   641     /// Changes the source of \c e to \c n
   642     ///
   643     /// Changes the source of \c e to \c n
   644     ///
   645     ///\note The <tt>Edge</tt>'s and <tt>InEdge</tt>'s
   646     ///referencing the changed edge remain
   647     ///valid. However <tt>OutEdge</tt>'s are invalidated.
   648     void changeSource(UEdge e, Node n) { 
   649       Parent::changeSource(e,n); 
   650     }
   651     /// \brief Contract two nodes.
   652     ///
   653     /// This function contracts two nodes.
   654     ///
   655     /// Node \p b will be removed but instead of deleting
   656     /// its neighboring edges, they will be joined to \p a.
   657     /// The last parameter \p r controls whether to remove loops. \c true
   658     /// means that loops will be removed.
   659     ///
   660     /// \note The <tt>Edge</tt>s
   661     /// referencing a moved edge remain
   662     /// valid.
   663     void contract(Node a, Node b, bool r = true) {
   664       for(IncEdgeIt e(*this, b); e!=INVALID;) {
   665 	IncEdgeIt f = e; ++f;
   666 	if (r && runningNode(e) == a) {
   667 	  erase(e);
   668 	} else if (source(e) == b) {
   669 	  changeSource(e, a);
   670 	} else {
   671 	  changeTarget(e, a);
   672 	}
   673 	e = f;
   674       }
   675       erase(b);
   676     }
   677   };
   678 
   679 
   680   class ListBpUGraphBase {
   681   public:
   682 
   683     class NodeSetError : public LogicError {
   684       virtual const char* exceptionName() const { 
   685 	return "lemon::ListBpUGraph::NodeSetError";
   686       }
   687     };
   688 
   689   protected:
   690 
   691     struct NodeT {
   692       int first_edge, prev, next;
   693     };
   694 
   695     struct UEdgeT {
   696       int aNode, prev_out, next_out;
   697       int bNode, prev_in, next_in;
   698     };
   699 
   700     std::vector<NodeT> aNodes;
   701     std::vector<NodeT> bNodes;
   702 
   703     std::vector<UEdgeT> edges;
   704 
   705     int first_anode;
   706     int first_free_anode;
   707 
   708     int first_bnode;
   709     int first_free_bnode;
   710 
   711     int first_free_edge;
   712 
   713   public:
   714   
   715     class Node {
   716       friend class ListBpUGraphBase;
   717     protected:
   718       int id;
   719 
   720       explicit Node(int _id) : id(_id) {}
   721     public:
   722       Node() {}
   723       Node(Invalid) { id = -1; }
   724       bool operator==(const Node i) const {return id==i.id;}
   725       bool operator!=(const Node i) const {return id!=i.id;}
   726       bool operator<(const Node i) const {return id<i.id;}
   727     };
   728 
   729     class UEdge {
   730       friend class ListBpUGraphBase;
   731     protected:
   732       int id;
   733 
   734       explicit UEdge(int _id) { id = _id;}
   735     public:
   736       UEdge() {}
   737       UEdge (Invalid) { id = -1; }
   738       bool operator==(const UEdge i) const {return id==i.id;}
   739       bool operator!=(const UEdge i) const {return id!=i.id;}
   740       bool operator<(const UEdge i) const {return id<i.id;}
   741     };
   742 
   743     ListBpUGraphBase()
   744       : first_anode(-1), first_free_anode(-1),
   745         first_bnode(-1), first_free_bnode(-1),
   746         first_free_edge(-1) {}
   747 
   748     void firstANode(Node& node) const {
   749       node.id = first_anode != -1 ? (first_anode << 1) : -1;
   750     }
   751     void nextANode(Node& node) const {
   752       node.id = aNodes[node.id >> 1].next;
   753     }
   754 
   755     void firstBNode(Node& node) const {
   756       node.id = first_bnode != -1 ? (first_bnode << 1) + 1 : -1;
   757     }
   758     void nextBNode(Node& node) const {
   759       node.id = bNodes[node.id >> 1].next;
   760     }
   761 
   762     void first(Node& node) const {
   763       if (first_anode != -1) {
   764         node.id = (first_anode << 1);
   765       } else if (first_bnode != -1) {
   766         node.id = (first_bnode << 1) + 1;
   767       } else {
   768         node.id = -1;
   769       }
   770     }
   771     void next(Node& node) const {
   772       if (aNode(node)) {
   773         node.id = aNodes[node.id >> 1].next;
   774         if (node.id == -1) {
   775           if (first_bnode != -1) {
   776             node.id = (first_bnode << 1) + 1;
   777           }
   778         }
   779       } else {
   780         node.id = bNodes[node.id >> 1].next;
   781       }
   782     }
   783   
   784     void first(UEdge& edge) const {
   785       int aNodeId = first_anode;
   786       while (aNodeId != -1 && aNodes[aNodeId].first_edge == -1) {
   787         aNodeId = aNodes[aNodeId].next != -1 ? 
   788           aNodes[aNodeId].next >> 1 : -1;
   789       }
   790       if (aNodeId != -1) {
   791         edge.id = aNodes[aNodeId].first_edge;
   792       } else {
   793         edge.id = -1;
   794       }
   795     }
   796     void next(UEdge& edge) const {
   797       int aNodeId = edges[edge.id].aNode >> 1;
   798       edge.id = edges[edge.id].next_out;
   799       if (edge.id == -1) {
   800         aNodeId = aNodes[aNodeId].next != -1 ? 
   801           aNodes[aNodeId].next >> 1 : -1;
   802         while (aNodeId != -1 && aNodes[aNodeId].first_edge == -1) {
   803           aNodeId = aNodes[aNodeId].next != -1 ? 
   804           aNodes[aNodeId].next >> 1 : -1;
   805         }
   806         if (aNodeId != -1) {
   807           edge.id = aNodes[aNodeId].first_edge;
   808         } else {
   809           edge.id = -1;
   810         }
   811       }
   812     }
   813 
   814     void firstFromANode(UEdge& edge, const Node& node) const {
   815       LEMON_ASSERT((node.id & 1) == 0, NodeSetError());
   816       edge.id = aNodes[node.id >> 1].first_edge;
   817     }
   818     void nextFromANode(UEdge& edge) const {
   819       edge.id = edges[edge.id].next_out;
   820     }
   821 
   822     void firstFromBNode(UEdge& edge, const Node& node) const {
   823       LEMON_ASSERT((node.id & 1) == 1, NodeSetError());
   824       edge.id = bNodes[node.id >> 1].first_edge;
   825     }
   826     void nextFromBNode(UEdge& edge) const {
   827       edge.id = edges[edge.id].next_in;
   828     }
   829 
   830     static int id(const Node& node) {
   831       return node.id;
   832     }
   833     static Node nodeFromId(int id) {
   834       return Node(id);
   835     }
   836     int maxNodeId() const {
   837       return aNodes.size() > bNodes.size() ?
   838 	aNodes.size() * 2 - 2 : bNodes.size() * 2 - 1;
   839     }
   840   
   841     static int id(const UEdge& edge) {
   842       return edge.id;
   843     }
   844     static UEdge uEdgeFromId(int id) {
   845       return UEdge(id);
   846     }
   847     int maxUEdgeId() const {
   848       return edges.size();
   849     }
   850   
   851     static int aNodeId(const Node& node) {
   852       return node.id >> 1;
   853     }
   854     static Node fromANodeId(int id) {
   855       return Node(id << 1);
   856     }
   857     int maxANodeId() const {
   858       return aNodes.size();
   859     }
   860 
   861     static int bNodeId(const Node& node) {
   862       return node.id >> 1;
   863     }
   864     static Node fromBNodeId(int id) {
   865       return Node((id << 1) + 1);
   866     }
   867     int maxBNodeId() const {
   868       return bNodes.size();
   869     }
   870 
   871     Node aNode(const UEdge& edge) const {
   872       return Node(edges[edge.id].aNode);
   873     }
   874     Node bNode(const UEdge& edge) const {
   875       return Node(edges[edge.id].bNode);
   876     }
   877 
   878     static bool aNode(const Node& node) {
   879       return (node.id & 1) == 0;
   880     }
   881 
   882     static bool bNode(const Node& node) {
   883       return (node.id & 1) == 1;
   884     }
   885 
   886     Node addANode() {
   887       int aNodeId;
   888       if (first_free_anode == -1) {
   889         aNodeId = aNodes.size();
   890         aNodes.push_back(NodeT());
   891       } else {
   892         aNodeId = first_free_anode;
   893         first_free_anode = aNodes[first_free_anode].next;
   894       }
   895       if (first_anode != -1) {
   896         aNodes[aNodeId].next = first_anode << 1;
   897         aNodes[first_anode].prev = aNodeId << 1;
   898       } else {
   899         aNodes[aNodeId].next = -1;
   900       }
   901       aNodes[aNodeId].prev = -1;
   902       first_anode = aNodeId;
   903       aNodes[aNodeId].first_edge = -1;
   904       return Node(aNodeId << 1);
   905     }
   906 
   907     Node addBNode() {
   908       int bNodeId;
   909       if (first_free_bnode == -1) {
   910         bNodeId = bNodes.size();
   911         bNodes.push_back(NodeT());
   912       } else {
   913         bNodeId = first_free_bnode;
   914         first_free_bnode = bNodes[first_free_bnode].next;
   915       }
   916       if (first_bnode != -1) {
   917         bNodes[bNodeId].next = (first_bnode << 1) + 1;
   918         bNodes[first_bnode].prev = (bNodeId << 1) + 1;
   919       } else {
   920         bNodes[bNodeId].next = -1;
   921       }
   922       first_bnode = bNodeId;
   923       bNodes[bNodeId].first_edge = -1;
   924       return Node((bNodeId << 1) + 1);
   925     }
   926 
   927     UEdge addEdge(const Node& source, const Node& target) {
   928       LEMON_ASSERT(((source.id ^ target.id) & 1) == 1, NodeSetError());
   929       int edgeId;
   930       if (first_free_edge != -1) {
   931         edgeId = first_free_edge;
   932         first_free_edge = edges[edgeId].next_out;
   933       } else {
   934         edgeId = edges.size();
   935         edges.push_back(UEdgeT());
   936       }
   937       if ((source.id & 1) == 0) {
   938 	edges[edgeId].aNode = source.id;
   939 	edges[edgeId].bNode = target.id;
   940       } else {
   941 	edges[edgeId].aNode = target.id;
   942 	edges[edgeId].bNode = source.id;
   943       }
   944       edges[edgeId].next_out = aNodes[edges[edgeId].aNode >> 1].first_edge;
   945       edges[edgeId].prev_out = -1;
   946       if (aNodes[edges[edgeId].aNode >> 1].first_edge != -1) {
   947         edges[aNodes[edges[edgeId].aNode >> 1].first_edge].prev_out = edgeId;
   948       }
   949       aNodes[edges[edgeId].aNode >> 1].first_edge = edgeId;
   950       edges[edgeId].next_in = bNodes[edges[edgeId].bNode >> 1].first_edge;
   951       edges[edgeId].prev_in = -1;
   952       if (bNodes[edges[edgeId].bNode >> 1].first_edge != -1) {
   953         edges[bNodes[edges[edgeId].bNode >> 1].first_edge].prev_in = edgeId;
   954       }
   955       bNodes[edges[edgeId].bNode >> 1].first_edge = edgeId;
   956       return UEdge(edgeId);
   957     }
   958 
   959     void erase(const Node& node) {
   960       if (aNode(node)) {
   961         int aNodeId = node.id >> 1;
   962         if (aNodes[aNodeId].prev != -1) {
   963           aNodes[aNodes[aNodeId].prev >> 1].next = aNodes[aNodeId].next;
   964         } else {
   965           first_anode = aNodes[aNodeId].next >> 1;
   966         }
   967         if (aNodes[aNodeId].next != -1) {
   968           aNodes[aNodes[aNodeId].next >> 1].prev = aNodes[aNodeId].prev;
   969         }
   970         aNodes[aNodeId].next = first_free_anode;
   971         first_free_anode = aNodeId;
   972       } else {
   973         int bNodeId = node.id >> 1;
   974         if (bNodes[bNodeId].prev != -1) {
   975           bNodes[bNodes[bNodeId].prev >> 1].next = bNodes[bNodeId].next;
   976         } else {
   977           first_bnode = bNodes[bNodeId].next >> 1;
   978         }
   979         if (bNodes[bNodeId].next != -1) {
   980           bNodes[bNodes[bNodeId].next >> 1].prev = bNodes[bNodeId].prev;
   981         }
   982         bNodes[bNodeId].next = first_free_bnode;
   983         first_free_bnode = bNodeId;
   984       }
   985     }
   986 
   987     void erase(const UEdge& edge) {
   988 
   989       if (edges[edge.id].prev_out != -1) {
   990         edges[edges[edge.id].prev_out].next_out = edges[edge.id].next_out;
   991       } else {
   992         aNodes[edges[edge.id].aNode >> 1].first_edge = edges[edge.id].next_out;
   993       }
   994       if (edges[edge.id].next_out != -1) {
   995         edges[edges[edge.id].next_out].prev_out = edges[edge.id].prev_out;
   996       }
   997 
   998       if (edges[edge.id].prev_in != -1) {
   999         edges[edges[edge.id].prev_in].next_in = edges[edge.id].next_in;
  1000       } else {
  1001         bNodes[edges[edge.id].bNode >> 1].first_edge = edges[edge.id].next_in;
  1002       }
  1003       if (edges[edge.id].next_in != -1) {
  1004         edges[edges[edge.id].next_in].prev_in = edges[edge.id].prev_in;
  1005       }
  1006 
  1007       edges[edge.id].next_out = first_free_edge;
  1008       first_free_edge = edge.id;
  1009     }
  1010 
  1011     void clear() {
  1012       aNodes.clear();
  1013       bNodes.clear();
  1014       edges.clear();
  1015       first_anode = -1;
  1016       first_free_anode = -1;
  1017       first_bnode = -1;
  1018       first_free_bnode = -1;
  1019       first_free_edge = -1;
  1020     }
  1021 
  1022   };
  1023 
  1024 
  1025   typedef BpUGraphExtender< ListBpUGraphBase > ExtendedListBpUGraphBase;
  1026 
  1027   /// \ingroup graphs
  1028   ///
  1029   /// \brief A smart bipartite undirected graph class.
  1030   ///
  1031   /// This is a bipartite undirected graph implementation.
  1032   /// It is conforms to the \ref concept::ErasableBpUGraph "ErasableBpUGraph" 
  1033   /// concept.
  1034   /// \sa concept::BpUGraph.
  1035   ///
  1036   class ListBpUGraph : public ExtendedListBpUGraphBase {};
  1037 
  1038   
  1039   /// @}  
  1040 } //namespace lemon
  1041   
  1042 
  1043 #endif