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