lemon/list_graph.h
author deba
Mon, 03 Apr 2006 09:45:23 +0000
changeset 2031 080d51024ac5
parent 1999 2ff283124dfc
child 2076 10681ee9d8ae
permissions -rw-r--r--
Correcting the structure of the graph's and adaptor's map.
The template assign operators and map iterators can be used for adaptors also.

Some bugfix in the adaptors

New class SwapBpUGraphAdaptor which swaps the two nodeset of the 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 addition that it conforms to the
   320   ///\ref concept::ErasableGraph "ErasableGraph" concept,
   321   ///it also provides several additional useful extra functionalities.
   322   ///\sa concept::ErasableGraph.
   323 
   324   class ListGraph : public ExtendedListGraphBase {
   325   public:
   326 
   327     typedef ExtendedListGraphBase Parent;
   328 
   329     /// Changes the target of \c e to \c n
   330 
   331     /// Changes the target of \c e to \c n
   332     ///
   333     ///\note The <tt>Edge</tt>'s and <tt>OutEdge</tt>'s
   334     ///referencing the changed edge remain
   335     ///valid. However <tt>InEdge</tt>'s are invalidated.
   336     void changeTarget(Edge e, Node n) { 
   337       _changeTarget(e,n); 
   338     }
   339     /// Changes the source of \c e to \c n
   340 
   341     /// Changes the source of \c e to \c n
   342     ///
   343     ///\note The <tt>Edge</tt>'s and <tt>InEdge</tt>'s
   344     ///referencing the changed edge remain
   345     ///valid. However <tt>OutEdge</tt>'s are invalidated.
   346     void changeSource(Edge e, Node n) { 
   347       _changeSource(e,n);
   348     }
   349 
   350     /// Invert the direction of an edge.
   351 
   352     ///\note The <tt>Edge</tt>'s
   353     ///referencing the changed edge remain
   354     ///valid. However <tt>OutEdge</tt>'s  and <tt>InEdge</tt>'s are invalidated.
   355     void reverseEdge(Edge e) {
   356       Node t=target(e);
   357       _changeTarget(e,source(e));
   358       _changeSource(e,t);
   359     }
   360 
   361     ///Using this it possible to avoid the superfluous memory allocation.
   362 
   363     ///Using this it possible to avoid the superfluous memory allocation.
   364     ///\todo more docs...
   365     void reserveEdge(int n) { edges.reserve(n); };
   366 
   367     ///Contract two nodes.
   368 
   369     ///This function contracts two nodes.
   370     ///
   371     ///Node \p b will be removed but instead of deleting
   372     ///its neighboring edges, they will be joined to \p a.
   373     ///The last parameter \p r controls whether to remove loops. \c true
   374     ///means that loops will be removed.
   375     ///
   376     ///\note The <tt>Edge</tt>s
   377     ///referencing a moved edge remain
   378     ///valid. However <tt>InEdge</tt>'s and <tt>OutEdge</tt>'s
   379     ///may be invalidated.
   380     void contract(Node a, Node b, bool r = true) 
   381     {
   382       for(OutEdgeIt e(*this,b);e!=INVALID;) {
   383 	OutEdgeIt f=e;
   384 	++f;
   385 	if(r && target(e)==a) erase(e);
   386 	else changeSource(e,a);
   387 	e=f;
   388       }
   389       for(InEdgeIt e(*this,b);e!=INVALID;) {
   390 	InEdgeIt f=e;
   391 	++f;
   392 	if(r && source(e)==a) erase(e);
   393 	else changeTarget(e,a);
   394 	e=f;
   395       }
   396       erase(b);
   397     }
   398 
   399     ///Split a node.
   400 
   401     ///This function splits a node. First a new node is added to the graph,
   402     ///then the source of each outgoing edge of \c n is moved to this new node.
   403     ///If \c connect is \c true (this is the default value), then a new edge
   404     ///from \c n to the newly created node is also added.
   405     ///\return The newly created node.
   406     ///
   407     ///\note The <tt>Edge</tt>s
   408     ///referencing a moved edge remain
   409     ///valid. However <tt>InEdge</tt>'s and <tt>OutEdge</tt>'s
   410     ///may be invalidated.
   411     ///\warning This functionality cannot be used together with the Snapshot
   412     ///feature.
   413     ///\todo It could be implemented in a bit faster way.
   414     Node split(Node n, bool connect = true) 
   415     {
   416       Node b = addNode();
   417       for(OutEdgeIt e(*this,n);e!=INVALID;) {
   418  	OutEdgeIt f=e;
   419 	++f;
   420 	changeSource(e,b);
   421 	e=f;
   422       }
   423       if(connect) addEdge(n,b);
   424       return b;
   425     }
   426       
   427     ///Split an edge.
   428 
   429     ///This function splits an edge. First a new node \c b is added to the graph,
   430     ///then the original edge is re-targetes to \c b. Finally an edge
   431     ///from \c b to the original target is added.
   432     ///\return The newly created node.
   433     ///\warning This functionality cannot be used together with the Snapshot
   434     ///feature.
   435     Node split(Edge e) 
   436     {
   437       Node b = addNode();
   438       addEdge(b,target(e));
   439       changeTarget(e,b);
   440       return b;
   441     }
   442       
   443     ///Class to make a snapshot of the graph and to restrore to it later.
   444 
   445     ///Class to make a snapshot of the graph and to restrore to it later.
   446     ///
   447     ///The newly added nodes and edges can be removed using the
   448     ///restore() function.
   449     ///
   450     ///\warning Edge and node deletions cannot be restored.
   451     ///\warning Snapshots cannot be nested.
   452     class Snapshot : protected Parent::NodeNotifier::ObserverBase,
   453 		     protected Parent::EdgeNotifier::ObserverBase
   454     {
   455     public:
   456       
   457       class UnsupportedOperation : public LogicError {
   458       public:
   459 	virtual const char* exceptionName() const {
   460 	  return "lemon::ListGraph::Snapshot::UnsupportedOperation";
   461 	}
   462       };
   463             
   464 
   465     protected:
   466       
   467       ListGraph *g;
   468       std::list<Node> added_nodes;
   469       std::list<Edge> added_edges;
   470       
   471       bool active;
   472       virtual void add(const Node& n) {
   473 	added_nodes.push_back(n);
   474       };
   475       virtual void erase(const Node&) 
   476       {
   477 	throw UnsupportedOperation();
   478       }
   479       virtual void add(const Edge& n) {
   480 	added_edges.push_back(n);
   481       };
   482       virtual void erase(const Edge&) 
   483       {
   484 	throw UnsupportedOperation();
   485       }
   486 
   487       ///\bug What is this used for?
   488       ///
   489       virtual void build() {}
   490       ///\bug What is this used for?
   491       ///
   492       virtual void clear() {}
   493 
   494       void regist(ListGraph &_g) {
   495 	g=&_g;
   496 	Parent::NodeNotifier::ObserverBase::attach(g->getNotifier(Node()));
   497 	Parent::EdgeNotifier::ObserverBase::attach(g->getNotifier(Edge()));
   498       }
   499             
   500       void deregist() {
   501 	Parent::NodeNotifier::ObserverBase::detach();
   502 	Parent::EdgeNotifier::ObserverBase::detach();
   503 	g=0;
   504       }
   505 
   506     public:
   507       ///Default constructur.
   508       
   509       ///Default constructur.
   510       ///To actually make a snapshot you must call save().
   511       ///
   512       Snapshot() : g(0) {}
   513       ///Constructor that immediately makes a snapshot.
   514       
   515       ///This constructor immediately makes a snapshot of the graph.
   516       ///\param _g The graph we make a snapshot of.
   517       Snapshot(ListGraph &_g) {
   518 	regist(_g);
   519       }
   520       ///\bug Is it necessary?
   521       ///
   522       ~Snapshot() 
   523       {
   524 	if(g) deregist();
   525       }
   526       
   527       ///Make a snapshot.
   528 
   529       ///Make a snapshot of the graph.
   530       ///
   531       ///This function can be called more than once. In case of a repeated
   532       ///call, the previous snapshot gets lost.
   533       ///\param _g The graph we make the snapshot of.
   534       void save(ListGraph &_g) 
   535       {
   536 	if(g!=&_g) {
   537 	  if(g) deregist();
   538 	  regist(_g);
   539 	}
   540 	added_nodes.clear();
   541 	added_edges.clear();
   542       }
   543       
   544     ///Undo the changes until the last snapshot.
   545 
   546     ///Undo the changes until last snapshot created by save().
   547     ///
   548     ///\todo This function might be called undo().
   549       void restore() {
   550 	ListGraph &old_g=*g;
   551 	deregist();
   552 	while(!added_edges.empty()) {
   553 	  old_g.erase(added_edges.front());
   554 	  added_edges.pop_front();
   555 	}
   556  	while(!added_nodes.empty()) {
   557 	  old_g.erase(added_nodes.front());
   558 	  added_nodes.pop_front();
   559 	}
   560       }
   561     };
   562     
   563   };
   564 
   565   ///@}
   566 
   567   /**************** Undirected List Graph ****************/
   568 
   569   typedef UGraphExtender<UGraphBaseExtender<
   570     ListGraphBase> > ExtendedListUGraphBase;
   571 
   572   /// \addtogroup graphs
   573   /// @{
   574 
   575   ///An undirected list graph class.
   576 
   577   ///This is a simple and fast erasable undirected graph implementation.
   578   ///
   579   ///It conforms to the
   580   ///\ref concept::UGraph "UGraph" concept.
   581   ///
   582   ///\sa concept::UGraph.
   583   ///
   584   ///\todo Snapshot, reverseEdge(), changeTarget(), changeSource(), contract()
   585   ///haven't been implemented yet.
   586   ///
   587   class ListUGraph : public ExtendedListUGraphBase {
   588   public:
   589     typedef ExtendedListUGraphBase Parent;
   590     /// \brief Changes the target of \c e to \c n
   591     ///
   592     /// Changes the target of \c e to \c n
   593     ///
   594     /// \note The <tt>Edge</tt>'s and <tt>OutEdge</tt>'s
   595     /// referencing the changed edge remain
   596     /// valid. However <tt>InEdge</tt>'s are invalidated.
   597     void changeTarget(UEdge e, Node n) { 
   598       _changeTarget(e,n); 
   599     }
   600     /// Changes the source of \c e to \c n
   601     ///
   602     /// Changes the source of \c e to \c n
   603     ///
   604     ///\note The <tt>Edge</tt>'s and <tt>InEdge</tt>'s
   605     ///referencing the changed edge remain
   606     ///valid. However <tt>OutEdge</tt>'s are invalidated.
   607     void changeSource(UEdge e, Node n) { 
   608       _changeSource(e,n); 
   609     }
   610     /// \brief Contract two nodes.
   611     ///
   612     /// This function contracts two nodes.
   613     ///
   614     /// Node \p b will be removed but instead of deleting
   615     /// its neighboring edges, they will be joined to \p a.
   616     /// The last parameter \p r controls whether to remove loops. \c true
   617     /// means that loops will be removed.
   618     ///
   619     /// \note The <tt>Edge</tt>s
   620     /// referencing a moved edge remain
   621     /// valid.
   622     void contract(Node a, Node b, bool r = true) {
   623       for(IncEdgeIt e(*this, b); e!=INVALID;) {
   624 	IncEdgeIt f = e; ++f;
   625 	if (r && runningNode(e) == a) {
   626 	  erase(e);
   627 	} else if (source(e) == b) {
   628 	  changeSource(e, a);
   629 	} else {
   630 	  changeTarget(e, a);
   631 	}
   632 	e = f;
   633       }
   634       erase(b);
   635     }
   636   };
   637 
   638 
   639   class ListBpUGraphBase {
   640   public:
   641 
   642     class NodeSetError : public LogicError {
   643       virtual const char* exceptionName() const { 
   644 	return "lemon::ListBpUGraph::NodeSetError";
   645       }
   646     };
   647 
   648   protected:
   649 
   650     struct NodeT {
   651       int first_edge, next_node;
   652     };
   653 
   654     struct EdgeT {
   655       int aNode, prev_out, next_out;
   656       int bNode, prev_in, next_in;
   657     };
   658 
   659     std::vector<NodeT> aNodes;
   660     std::vector<NodeT> bNodes;
   661 
   662     std::vector<EdgeT> edges;
   663 
   664     int first_anode;
   665     int first_free_anode;
   666 
   667     int first_bnode;
   668     int first_free_bnode;
   669 
   670     int first_free_edge;
   671 
   672   public:
   673   
   674     class Node {
   675       friend class ListBpUGraphBase;
   676     protected:
   677       int id;
   678 
   679       explicit Node(int _id) : id(_id) {}
   680     public:
   681       Node() {}
   682       Node(Invalid) { id = -1; }
   683       bool operator==(const Node i) const {return id==i.id;}
   684       bool operator!=(const Node i) const {return id!=i.id;}
   685       bool operator<(const Node i) const {return id<i.id;}
   686     };
   687 
   688     class Edge {
   689       friend class ListBpUGraphBase;
   690     protected:
   691       int id;
   692 
   693       explicit Edge(int _id) { id = _id;}
   694     public:
   695       Edge() {}
   696       Edge (Invalid) { id = -1; }
   697       bool operator==(const Edge i) const {return id==i.id;}
   698       bool operator!=(const Edge i) const {return id!=i.id;}
   699       bool operator<(const Edge i) const {return id<i.id;}
   700     };
   701 
   702     ListBpUGraphBase()
   703       : first_anode(-1), first_free_anode(-1),
   704         first_bnode(-1), first_free_bnode(-1),
   705         first_free_edge(-1) {}
   706 
   707     void firstANode(Node& node) const {
   708       node.id = first_anode != -1 ? (first_anode << 1) : -1;
   709     }
   710     void nextANode(Node& node) const {
   711       node.id = aNodes[node.id >> 1].next_node;
   712     }
   713 
   714     void firstBNode(Node& node) const {
   715       node.id =  first_bnode != -1 ? (first_bnode << 1) + 1 : -1;
   716     }
   717     void nextBNode(Node& node) const {
   718       node.id = bNodes[node.id >> 1].next_node;
   719     }
   720 
   721     void first(Node& node) const {
   722       if (first_anode != -1) {
   723         node.id = (first_anode << 1);
   724       } else if (first_bnode != -1) {
   725         node.id = (first_bnode << 1) + 1;
   726       } else {
   727         node.id = -1;
   728       }
   729     }
   730     void next(Node& node) const {
   731       if (aNode(node)) {
   732         node.id = aNodes[node.id >> 1].next_node;
   733         if (node.id == -1) {
   734           if (first_bnode != -1) {
   735             node.id = (first_bnode << 1) + 1;
   736           }
   737         }
   738       } else {
   739         node.id = bNodes[node.id >> 1].next_node;
   740       }
   741     }
   742   
   743     void first(Edge& edge) const {
   744       int aNodeId = first_anode;
   745       while (aNodeId != -1 && aNodes[aNodeId].first_edge == -1) {
   746         aNodeId = aNodes[aNodeId].next_node != -1 ? 
   747           aNodes[aNodeId].next_node >> 1 : -1;
   748       }
   749       if (aNodeId != -1) {
   750         edge.id = aNodes[aNodeId].first_edge;
   751       } else {
   752         edge.id = -1;
   753       }
   754     }
   755     void next(Edge& edge) const {
   756       int aNodeId = edges[edge.id].aNode >> 1;
   757       edge.id = edges[edge.id].next_out;
   758       if (edge.id == -1) {
   759         aNodeId = aNodes[aNodeId].next_node != -1 ? 
   760           aNodes[aNodeId].next_node >> 1 : -1;
   761         while (aNodeId != -1 && aNodes[aNodeId].first_edge == -1) {
   762           aNodeId = aNodes[aNodeId].next_node != -1 ? 
   763           aNodes[aNodeId].next_node >> 1 : -1;
   764         }
   765         if (aNodeId != -1) {
   766           edge.id = aNodes[aNodeId].first_edge;
   767         } else {
   768           edge.id = -1;
   769         }
   770       }
   771     }
   772 
   773     void firstOut(Edge& edge, const Node& node) const {
   774       LEMON_ASSERT((node.id & 1) == 0, NodeSetError());
   775       edge.id = aNodes[node.id >> 1].first_edge;
   776     }
   777     void nextOut(Edge& edge) const {
   778       edge.id = edges[edge.id].next_out;
   779     }
   780 
   781     void firstIn(Edge& edge, const Node& node) const {
   782       LEMON_ASSERT((node.id & 1) == 1, NodeSetError());
   783       edge.id = bNodes[node.id >> 1].first_edge;
   784     }
   785     void nextIn(Edge& edge) const {
   786       edge.id = edges[edge.id].next_in;
   787     }
   788 
   789     static int id(const Node& node) {
   790       return node.id;
   791     }
   792     static Node nodeFromId(int id) {
   793       return Node(id);
   794     }
   795     int maxNodeId() const {
   796       return aNodes.size() > bNodes.size() ?
   797 	aNodes.size() * 2 - 2 : bNodes.size() * 2 - 1;
   798     }
   799   
   800     static int id(const Edge& edge) {
   801       return edge.id;
   802     }
   803     static Edge edgeFromId(int id) {
   804       return Edge(id);
   805     }
   806     int maxEdgeId() const {
   807       return edges.size();
   808     }
   809   
   810     static int aNodeId(const Node& node) {
   811       return node.id >> 1;
   812     }
   813     static Node fromANodeId(int id) {
   814       return Node(id << 1);
   815     }
   816     int maxANodeId() const {
   817       return aNodes.size();
   818     }
   819 
   820     static int bNodeId(const Node& node) {
   821       return node.id >> 1;
   822     }
   823     static Node fromBNodeId(int id) {
   824       return Node((id << 1) + 1);
   825     }
   826     int maxBNodeId() const {
   827       return bNodes.size();
   828     }
   829 
   830     Node aNode(const Edge& edge) const {
   831       return Node(edges[edge.id].aNode);
   832     }
   833     Node bNode(const Edge& edge) const {
   834       return Node(edges[edge.id].bNode);
   835     }
   836 
   837     static bool aNode(const Node& node) {
   838       return (node.id & 1) == 0;
   839     }
   840 
   841     static bool bNode(const Node& node) {
   842       return (node.id & 1) == 1;
   843     }
   844 
   845     Node addANode() {
   846       int aNodeId;
   847       if (first_free_anode == -1) {
   848         aNodeId = aNodes.size();
   849         aNodes.push_back(NodeT());
   850       } else {
   851         aNodeId = first_free_anode;
   852         first_free_anode = aNodes[first_free_anode].next_node;
   853       }
   854       aNodes[aNodeId].next_node = 
   855         first_anode != -1 ? (first_anode << 1) : -1;
   856       first_anode = aNodeId;
   857       aNodes[aNodeId].first_edge = -1;
   858       return Node(aNodeId << 1);
   859     }
   860 
   861     Node addBNode() {
   862       int bNodeId;
   863       if (first_free_bnode == -1) {
   864         bNodeId = bNodes.size();
   865         bNodes.push_back(NodeT());
   866       } else {
   867         bNodeId = first_free_bnode;
   868         first_free_bnode = bNodes[first_free_bnode].next_node;
   869       }
   870       bNodes[bNodeId].next_node = 
   871         first_bnode != -1 ? (first_bnode << 1) + 1 : -1;
   872       first_bnode = bNodeId;
   873       bNodes[bNodeId].first_edge = -1;
   874       return Node((bNodeId << 1) + 1);
   875     }
   876 
   877     Edge addEdge(const Node& source, const Node& target) {
   878       LEMON_ASSERT(((source.id ^ target.id) & 1) == 1, NodeSetError());
   879       int edgeId;
   880       if (first_free_edge != -1) {
   881         edgeId = first_free_edge;
   882         first_free_edge = edges[edgeId].next_out;
   883       } else {
   884         edgeId = edges.size();
   885         edges.push_back(EdgeT());
   886       }
   887       if ((source.id & 1) == 0) {
   888 	edges[edgeId].aNode = source.id;
   889 	edges[edgeId].bNode = target.id;
   890       } else {
   891 	edges[edgeId].aNode = target.id;
   892 	edges[edgeId].bNode = source.id;
   893       }
   894       edges[edgeId].next_out = aNodes[edges[edgeId].aNode >> 1].first_edge;
   895       edges[edgeId].prev_out = -1;
   896       if (aNodes[edges[edgeId].aNode >> 1].first_edge != -1) {
   897         edges[aNodes[edges[edgeId].aNode >> 1].first_edge].prev_out = edgeId;
   898       }
   899       aNodes[edges[edgeId].aNode >> 1].first_edge = edgeId;
   900       edges[edgeId].next_in = bNodes[edges[edgeId].bNode >> 1].first_edge;
   901       edges[edgeId].prev_in = -1;
   902       if (bNodes[edges[edgeId].bNode >> 1].first_edge != -1) {
   903         edges[bNodes[edges[edgeId].bNode >> 1].first_edge].prev_in = edgeId;
   904       }
   905       bNodes[edges[edgeId].bNode >> 1].first_edge = edgeId;
   906       return Edge(edgeId);
   907     }
   908 
   909     void erase(const Node& node) {
   910       if (aNode(node)) {
   911         int aNodeId = node.id >> 1;
   912         aNodes[aNodeId].next_node = first_free_anode;
   913         first_free_anode = aNodeId;
   914       } else {
   915         int bNodeId = node.id >> 1;
   916         bNodes[bNodeId].next_node = first_free_bnode;
   917         first_free_bnode = bNodeId;
   918       }
   919     }
   920 
   921     void erase(const Edge& edge) {
   922       if (edges[edge.id].prev_out != -1) {
   923         edges[edges[edge.id].prev_out].next_out = edges[edge.id].next_out;
   924       } else {
   925         aNodes[edges[edge.id].aNode].first_edge = edges[edge.id].next_out;
   926       }
   927       if (edges[edge.id].next_out != -1) {
   928         edges[edges[edge.id].next_out].prev_out = edges[edge.id].prev_out;
   929       }
   930       if (edges[edge.id].prev_in != -1) {
   931         edges[edges[edge.id].prev_in].next_in = edges[edge.id].next_in;
   932       } else {
   933         bNodes[edges[edge.id].bNode].first_edge = edges[edge.id].next_in;
   934       }
   935       if (edges[edge.id].next_in != -1) {
   936         edges[edges[edge.id].next_in].prev_in = edges[edge.id].prev_in;
   937       }
   938       edges[edge.id].next_out = first_free_edge;
   939       first_free_edge = edge.id;
   940     }
   941 
   942     void clear() {
   943       aNodes.clear();
   944       bNodes.clear();
   945       edges.clear();
   946       first_anode = -1;
   947       first_free_anode = -1;
   948       first_bnode = -1;
   949       first_free_bnode = -1;
   950       first_free_edge = -1;
   951     }
   952 
   953   };
   954 
   955 
   956   typedef BpUGraphExtender< BpUGraphBaseExtender<
   957     ListBpUGraphBase> > ExtendedListBpUGraphBase;
   958 
   959   /// \ingroup graphs
   960   ///
   961   /// \brief A smart bipartite undirected graph class.
   962   ///
   963   /// This is a bipartite undirected graph implementation.
   964   /// It is conforms to the \ref concept::ErasableBpUGraph "ErasableBpUGraph" 
   965   /// concept.
   966   /// \sa concept::BpUGraph.
   967   ///
   968   class ListBpUGraph : public ExtendedListBpUGraphBase {};
   969 
   970   
   971   /// @}  
   972 } //namespace lemon
   973   
   974 
   975 #endif