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