lemon/smart_graph.h
author hegyi
Mon, 21 Nov 2005 18:03:20 +0000
changeset 1823 cb082cdf3667
parent 1791 62e7d237e1fb
child 1875 98698b69a902
permissions -rw-r--r--
NewMapWin has become Dialog instead of Window. Therefore it is created dynamically, when there is need for it, instead of keeping one instance in memory. This solution is slower, but more correct than before.
alpar@906
     1
/* -*- C++ -*-
ladanyi@1435
     2
 * lemon/smart_graph.h - Part of LEMON, a generic C++ optimization library
alpar@906
     3
 *
alpar@1164
     4
 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@1359
     5
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@906
     6
 *
alpar@906
     7
 * Permission to use, modify and distribute this software is granted
alpar@906
     8
 * provided that this copyright notice appears in all copies. For
alpar@906
     9
 * precise terms see the accompanying LICENSE file.
alpar@906
    10
 *
alpar@906
    11
 * This software is provided "AS IS" with no warranty of any kind,
alpar@906
    12
 * express or implied, and with no claim as to its suitability for any
alpar@906
    13
 * purpose.
alpar@906
    14
 *
alpar@906
    15
 */
alpar@105
    16
alpar@921
    17
#ifndef LEMON_SMART_GRAPH_H
alpar@921
    18
#define LEMON_SMART_GRAPH_H
alpar@104
    19
klao@491
    20
///\ingroup graphs
alpar@242
    21
///\file
deba@1692
    22
///\brief SmartGraph and UndirSmartGraph classes.
alpar@242
    23
alpar@104
    24
#include <vector>
alpar@104
    25
alpar@921
    26
#include <lemon/invalid.h>
alpar@157
    27
deba@1307
    28
#include <lemon/bits/clearable_graph_extender.h>
deba@1307
    29
#include <lemon/bits/extendable_graph_extender.h>
deba@1307
    30
#include <lemon/bits/iterable_graph_extender.h>
deba@1307
    31
#include <lemon/bits/alteration_notifier.h>
deba@1307
    32
#include <lemon/bits/default_map.h>
deba@1791
    33
#include <lemon/bits/graph_extender.h>
klao@1034
    34
klao@977
    35
#include <lemon/utility.h>
deba@1820
    36
#include <lemon/error.h>
deba@782
    37
alpar@921
    38
namespace lemon {
alpar@104
    39
alpar@973
    40
  class SmartGraph;
alpar@969
    41
  ///Base of SmartGraph
alpar@969
    42
alpar@969
    43
  ///Base of SmartGraph
alpar@969
    44
  ///
klao@946
    45
  class SmartGraphBase {
alpar@104
    46
alpar@973
    47
    friend class SmatGraph;
alpar@973
    48
alpar@973
    49
  protected:
alpar@104
    50
    struct NodeT 
alpar@104
    51
    {
alpar@104
    52
      int first_in,first_out;      
alpar@157
    53
      NodeT() : first_in(-1), first_out(-1) {}
alpar@104
    54
    };
alpar@104
    55
    struct EdgeT 
alpar@104
    56
    {
alpar@986
    57
      int target, source, next_in, next_out;      
alpar@104
    58
      //FIXME: is this necessary?
alpar@157
    59
      EdgeT() : next_in(-1), next_out(-1) {}  
alpar@104
    60
    };
alpar@104
    61
alpar@104
    62
    std::vector<NodeT> nodes;
alpar@129
    63
alpar@104
    64
    std::vector<EdgeT> edges;
alpar@104
    65
    
alpar@185
    66
    
alpar@104
    67
  public:
deba@782
    68
klao@946
    69
    typedef SmartGraphBase Graph;
alpar@104
    70
alpar@164
    71
    class Node;
alpar@164
    72
    class Edge;
alpar@108
    73
alpar@104
    74
    
alpar@104
    75
  public:
alpar@104
    76
klao@946
    77
    SmartGraphBase() : nodes(), edges() { }
deba@1718
    78
    SmartGraphBase(const SmartGraphBase &_g) 
deba@1718
    79
      : nodes(_g.nodes), edges(_g.edges) { }
alpar@104
    80
    
klao@977
    81
    typedef True NodeNumTag;
klao@977
    82
    typedef True EdgeNumTag;
klao@977
    83
alpar@813
    84
    ///Number of nodes.
alpar@813
    85
    int nodeNum() const { return nodes.size(); }
alpar@813
    86
    ///Number of edges.
alpar@813
    87
    int edgeNum() const { return edges.size(); }
alpar@104
    88
alpar@813
    89
    /// Maximum node ID.
alpar@813
    90
    
alpar@813
    91
    /// Maximum node ID.
alpar@813
    92
    ///\sa id(Node)
deba@1791
    93
    int maxNodeId() const { return nodes.size()-1; }
alpar@813
    94
    /// Maximum edge ID.
alpar@813
    95
    
alpar@813
    96
    /// Maximum edge ID.
alpar@813
    97
    ///\sa id(Edge)
deba@1791
    98
    int maxEdgeId() const { return edges.size()-1; }
alpar@108
    99
alpar@986
   100
    Node source(Edge e) const { return edges[e.n].source; }
alpar@986
   101
    Node target(Edge e) const { return edges[e.n].target; }
alpar@104
   102
alpar@813
   103
    /// Node ID.
alpar@813
   104
    
alpar@813
   105
    /// The ID of a valid Node is a nonnegative integer not greater than
deba@1791
   106
    /// \ref maxNodeId(). The range of the ID's is not surely continuous
deba@1791
   107
    /// and the greatest node ID can be actually less then \ref maxNodeId().
alpar@813
   108
    ///
alpar@813
   109
    /// The ID of the \ref INVALID node is -1.
alpar@813
   110
    ///\return The ID of the node \c v. 
alpar@713
   111
    static int id(Node v) { return v.n; }
alpar@813
   112
    /// Edge ID.
alpar@813
   113
    
alpar@813
   114
    /// The ID of a valid Edge is a nonnegative integer not greater than
deba@1791
   115
    /// \ref maxEdgeId(). The range of the ID's is not surely continuous
deba@1791
   116
    /// and the greatest edge ID can be actually less then \ref maxEdgeId().
alpar@813
   117
    ///
alpar@813
   118
    /// The ID of the \ref INVALID edge is -1.
alpar@813
   119
    ///\return The ID of the edge \c e. 
alpar@713
   120
    static int id(Edge e) { return e.n; }
alpar@104
   121
deba@1791
   122
    static Node nodeFromId(int id) { return Node(id);}
deba@1106
   123
deba@1791
   124
    static Edge edgeFromId(int id) { return Edge(id);}
deba@1106
   125
alpar@164
   126
    Node addNode() {
alpar@164
   127
      Node n; n.n=nodes.size();
alpar@104
   128
      nodes.push_back(NodeT()); //FIXME: Hmmm...
alpar@104
   129
      return n;
alpar@104
   130
    }
alpar@108
   131
    
alpar@164
   132
    Edge addEdge(Node u, Node v) {
alpar@164
   133
      Edge e; e.n=edges.size(); edges.push_back(EdgeT()); //FIXME: Hmmm...
alpar@986
   134
      edges[e.n].source=u.n; edges[e.n].target=v.n;
alpar@104
   135
      edges[e.n].next_out=nodes[u.n].first_out;
alpar@104
   136
      edges[e.n].next_in=nodes[v.n].first_in;
alpar@104
   137
      nodes[u.n].first_out=nodes[v.n].first_in=e.n;
alpar@108
   138
alpar@104
   139
      return e;
alpar@104
   140
    }
alpar@104
   141
deba@782
   142
    void clear() {
deba@782
   143
      edges.clear();
deba@782
   144
      nodes.clear();
deba@782
   145
    }
alpar@104
   146
klao@946
   147
alpar@164
   148
    class Node {
klao@946
   149
      friend class SmartGraphBase;
alpar@973
   150
      friend class SmartGraph;
alpar@104
   151
alpar@104
   152
    protected:
alpar@104
   153
      int n;
alpar@164
   154
      Node(int nn) {n=nn;}
alpar@104
   155
    public:
alpar@164
   156
      Node() {}
alpar@503
   157
      Node (Invalid) { n=-1; }
alpar@164
   158
      bool operator==(const Node i) const {return n==i.n;}
alpar@164
   159
      bool operator!=(const Node i) const {return n!=i.n;}
alpar@164
   160
      bool operator<(const Node i) const {return n<i.n;}
alpar@104
   161
    };
alpar@104
   162
    
alpar@104
   163
alpar@164
   164
    class Edge {
klao@946
   165
      friend class SmartGraphBase;
alpar@973
   166
      friend class SmartGraph;
alpar@185
   167
alpar@104
   168
    protected:
alpar@104
   169
      int n;
alpar@905
   170
      Edge(int nn) {n=nn;}
alpar@706
   171
    public:
alpar@164
   172
      Edge() { }
marci@174
   173
      Edge (Invalid) { n=-1; }
alpar@164
   174
      bool operator==(const Edge i) const {return n==i.n;}
alpar@164
   175
      bool operator!=(const Edge i) const {return n!=i.n;}
alpar@164
   176
      bool operator<(const Edge i) const {return n<i.n;}
klao@946
   177
    };
alpar@905
   178
klao@946
   179
    void first(Node& node) const {
klao@946
   180
      node.n = nodes.size() - 1;
klao@946
   181
    }
klao@946
   182
klao@946
   183
    static void next(Node& node) {
klao@946
   184
      --node.n;
klao@946
   185
    }
klao@946
   186
klao@946
   187
    void first(Edge& edge) const {
klao@946
   188
      edge.n = edges.size() - 1;
klao@946
   189
    }
klao@946
   190
klao@946
   191
    static void next(Edge& edge) {
klao@946
   192
      --edge.n;
klao@946
   193
    }
klao@946
   194
klao@946
   195
    void firstOut(Edge& edge, const Node& node) const {
klao@946
   196
      edge.n = nodes[node.n].first_out;
klao@946
   197
    }
klao@946
   198
klao@946
   199
    void nextOut(Edge& edge) const {
klao@946
   200
      edge.n = edges[edge.n].next_out;
klao@946
   201
    }
klao@946
   202
klao@946
   203
    void firstIn(Edge& edge, const Node& node) const {
klao@946
   204
      edge.n = nodes[node.n].first_in;
klao@946
   205
    }
alpar@104
   206
    
klao@946
   207
    void nextIn(Edge& edge) const {
klao@946
   208
      edge.n = edges[edge.n].next_in;
klao@946
   209
    }
alpar@105
   210
alpar@1284
   211
    Node _split(Node n, bool connect = true)
alpar@1284
   212
    {
alpar@1284
   213
      Node b = addNode();
alpar@1284
   214
      nodes[b.n].first_out=nodes[n.n].first_out;
alpar@1284
   215
      nodes[n.n].first_out=-1;
alpar@1284
   216
      for(int i=nodes[b.n].first_out;i!=-1;i++) edges[i].source=b.n;
alpar@1284
   217
      if(connect) addEdge(n,b);
alpar@1284
   218
      return b;
alpar@1284
   219
    }
alpar@1284
   220
alpar@104
   221
  };
alpar@185
   222
deba@1669
   223
  typedef ClearableGraphExtender<
deba@1669
   224
    ExtendableGraphExtender<
deba@1669
   225
    MappableGraphExtender<
deba@1669
   226
    IterableGraphExtender<
deba@1791
   227
    AlterableGraphExtender<
deba@1791
   228
    GraphExtender<SmartGraphBase> > > > > > ExtendedSmartGraphBase;
deba@937
   229
deba@1791
   230
  /// \ingroup graphs
alpar@1161
   231
alpar@950
   232
  ///A smart graph class.
deba@937
   233
alpar@950
   234
  ///This is a simple and fast graph implementation.
alpar@950
   235
  ///It is also quite memory efficient, but at the price
alpar@974
   236
  ///that <b> it does support only limited (only stack-like)
alpar@974
   237
  ///node and edge deletions</b>.
alpar@950
   238
  ///It conforms to 
klao@959
   239
  ///the \ref concept::ExtendableGraph "ExtendableGraph" concept.
klao@959
   240
  ///\sa concept::ExtendableGraph.
alpar@950
   241
  ///
alpar@950
   242
  ///\author Alpar Juttner
deba@1669
   243
  class SmartGraph : public ExtendedSmartGraphBase {
alpar@969
   244
  public:
alpar@973
   245
    
alpar@1770
   246
    class Snapshot;
alpar@1770
   247
    friend class Snapshot;
alpar@973
   248
alpar@1011
   249
  protected:
alpar@1770
   250
    void restoreSnapshot(const Snapshot &s)
alpar@973
   251
    {
alpar@1457
   252
      while(s.edge_num<edges.size()) {
deba@1040
   253
	Parent::getNotifier(Edge()).erase(Edge(edges.size()-1));
alpar@986
   254
	nodes[edges.back().target].first_in=edges.back().next_in;
alpar@986
   255
	nodes[edges.back().source].first_out=edges.back().next_out;
alpar@973
   256
	edges.pop_back();
alpar@973
   257
      }
alpar@973
   258
      //nodes.resize(s.nodes_num);
alpar@1457
   259
      while(s.node_num<nodes.size()) {
deba@1040
   260
	Parent::getNotifier(Node()).erase(Node(nodes.size()-1));
alpar@973
   261
	nodes.pop_back();
alpar@973
   262
      }
alpar@1011
   263
    }    
alpar@1011
   264
alpar@1011
   265
  public:
alpar@1284
   266
alpar@1284
   267
    ///Split a node.
alpar@1284
   268
    
alpar@1284
   269
    ///This function splits a node. First a new node is added to the graph,
alpar@1284
   270
    ///then the source of each outgoing edge of \c n is moved to this new node.
alpar@1284
   271
    ///If \c connect is \c true (this is the default value), then a new edge
alpar@1284
   272
    ///from \c n to the newly created node is also added.
alpar@1284
   273
    ///\return The newly created node.
alpar@1284
   274
    ///
alpar@1284
   275
    ///\note The <tt>Edge</tt>s
alpar@1284
   276
    ///referencing a moved edge remain
alpar@1284
   277
    ///valid. However <tt>InEdge</tt>'s and <tt>OutEdge</tt>'s
alpar@1284
   278
    ///may be invalidated.
alpar@1770
   279
    ///\warning This functionality cannot be used together with the Snapshot
alpar@1284
   280
    ///feature.
alpar@1284
   281
    ///\todo It could be implemented in a bit faster way.
alpar@1284
   282
    Node split(Node n, bool connect = true) 
alpar@1284
   283
    {
deba@1718
   284
      Node b = _split(n,connect);
deba@1718
   285
      return b;
alpar@1284
   286
    }
alpar@1284
   287
  
alpar@1284
   288
alpar@1011
   289
    ///Class to make a snapshot of the graph and to restrore to it later.
alpar@1011
   290
alpar@1011
   291
    ///Class to make a snapshot of the graph and to restrore to it later.
alpar@1011
   292
    ///
alpar@1011
   293
    ///The newly added nodes and edges can be removed using the
alpar@1011
   294
    ///restore() function.
alpar@1011
   295
    ///\note After you restore a state, you cannot restore
alpar@1011
   296
    ///a later state, in other word you cannot add again the edges deleted
alpar@1770
   297
    ///by restore() using another Snapshot instance.
alpar@1011
   298
    ///
alpar@1770
   299
    class Snapshot 
alpar@1011
   300
    {
alpar@1011
   301
      SmartGraph *g;
alpar@1011
   302
    protected:
alpar@1011
   303
      friend class SmartGraph;
alpar@1011
   304
      unsigned int node_num;
alpar@1011
   305
      unsigned int edge_num;
alpar@1011
   306
    public:
zsuzska@1274
   307
      ///Default constructor.
alpar@1011
   308
      
zsuzska@1274
   309
      ///Default constructor.
alpar@1011
   310
      ///To actually make a snapshot you must call save().
alpar@1011
   311
      ///
alpar@1770
   312
      Snapshot() : g(0) {}
alpar@1011
   313
      ///Constructor that immediately makes a snapshot
alpar@1011
   314
      
alpar@1011
   315
      ///This constructor immediately makes a snapshot of the graph.
alpar@1011
   316
      ///\param _g The graph we make a snapshot of.
alpar@1770
   317
      Snapshot(SmartGraph &_g) :g(&_g) {
alpar@1011
   318
	node_num=g->nodes.size();
alpar@1011
   319
	edge_num=g->edges.size();
alpar@1011
   320
      }
alpar@1011
   321
alpar@1011
   322
      ///Make a snapshot.
alpar@1011
   323
alpar@1011
   324
      ///Make a snapshot of the graph.
alpar@1011
   325
      ///
alpar@1011
   326
      ///This function can be called more than once. In case of a repeated
alpar@1011
   327
      ///call, the previous snapshot gets lost.
alpar@1011
   328
      ///\param _g The graph we make the snapshot of.
alpar@1011
   329
      void save(SmartGraph &_g) 
alpar@1011
   330
      {
alpar@1011
   331
	g=&_g;
alpar@1011
   332
	node_num=g->nodes.size();
alpar@1011
   333
	edge_num=g->edges.size();
alpar@1011
   334
      }
alpar@1011
   335
alpar@1011
   336
      ///Undo the changes until a snapshot.
alpar@1011
   337
      
alpar@1011
   338
      ///Undo the changes until a snapshot created by save().
alpar@1011
   339
      ///
alpar@1011
   340
      ///\note After you restored a state, you cannot restore
alpar@1011
   341
      ///a later state, in other word you cannot add again the edges deleted
alpar@1011
   342
      ///by restore().
alpar@1011
   343
      ///
alpar@1011
   344
      ///\todo This function might be called undo().
alpar@1011
   345
      
alpar@1011
   346
      void restore()
alpar@1011
   347
      {
alpar@1770
   348
	g->restoreSnapshot(*this);
alpar@1011
   349
      }
alpar@1011
   350
    };
alpar@973
   351
  };
klao@1034
   352
klao@1034
   353
klao@1034
   354
  /**************** Undirected List Graph ****************/
klao@1034
   355
klao@1034
   356
  typedef ClearableUndirGraphExtender<
klao@1034
   357
    ExtendableUndirGraphExtender<
klao@1034
   358
    MappableUndirGraphExtender<
klao@1034
   359
    IterableUndirGraphExtender<
klao@1034
   360
    AlterableUndirGraphExtender<
deba@1669
   361
    UndirGraphExtender<SmartGraphBase> > > > > > ExtendedUndirSmartGraphBase;
klao@1034
   362
alpar@1035
   363
  ///A smart undirected graph class.
alpar@1035
   364
alpar@1035
   365
  ///This is a simple and fast undirected graph implementation.
alpar@1035
   366
  ///It is also quite memory efficient, but at the price
alpar@1035
   367
  ///that <b> it does support only limited (only stack-like)
alpar@1035
   368
  ///node and edge deletions</b>.
alpar@1035
   369
  ///Except from this it conforms to 
alpar@1035
   370
  ///the \ref concept::UndirGraph "UndirGraph" concept.
alpar@1035
   371
  ///\sa concept::UndirGraph.
alpar@1035
   372
  ///
alpar@1770
   373
  ///\todo Snapshot hasn't been implemented yet.
alpar@1035
   374
  ///
deba@1669
   375
  class UndirSmartGraph : public ExtendedUndirSmartGraphBase {
klao@1034
   376
  };
klao@1034
   377
deba@1820
   378
deba@1820
   379
  class SmartUndirBipartiteGraphBase {
deba@1820
   380
  public:
deba@1820
   381
deba@1820
   382
    class NodeSetError : public LogicError {
deba@1820
   383
      virtual const char* exceptionName() const { 
deba@1820
   384
	return "lemon::FullUndirBipartiteGraph::NodeSetError";
deba@1820
   385
      }
deba@1820
   386
    };
deba@1820
   387
deba@1820
   388
  protected:
deba@1820
   389
deba@1820
   390
    struct NodeT {
deba@1820
   391
      int first;
deba@1820
   392
      NodeT() {}
deba@1820
   393
      NodeT(int _first) : first(_first) {}
deba@1820
   394
    };
deba@1820
   395
deba@1820
   396
    struct EdgeT {
deba@1820
   397
      int upper, next_down;
deba@1820
   398
      int lower, next_up;
deba@1820
   399
    };
deba@1820
   400
deba@1820
   401
    std::vector<NodeT> upperNodes;
deba@1820
   402
    std::vector<NodeT> lowerNodes;
deba@1820
   403
deba@1820
   404
    std::vector<EdgeT> edges;
deba@1820
   405
deba@1820
   406
  public:
deba@1820
   407
  
deba@1820
   408
    class Node {
deba@1820
   409
      friend class SmartUndirBipartiteGraphBase;
deba@1820
   410
    protected:
deba@1820
   411
      int id;
deba@1820
   412
deba@1820
   413
      Node(int _id) : id(_id) {}
deba@1820
   414
    public:
deba@1820
   415
      Node() {}
deba@1820
   416
      Node(Invalid) { id = -1; }
deba@1820
   417
      bool operator==(const Node i) const {return id==i.id;}
deba@1820
   418
      bool operator!=(const Node i) const {return id!=i.id;}
deba@1820
   419
      bool operator<(const Node i) const {return id<i.id;}
deba@1820
   420
    };
deba@1820
   421
deba@1820
   422
    class Edge {
deba@1820
   423
      friend class SmartUndirBipartiteGraphBase;
deba@1820
   424
    protected:
deba@1820
   425
      int id;
deba@1820
   426
deba@1820
   427
      Edge(int _id) { id = _id;}
deba@1820
   428
    public:
deba@1820
   429
      Edge() {}
deba@1820
   430
      Edge (Invalid) { id = -1; }
deba@1820
   431
      bool operator==(const Edge i) const {return id==i.id;}
deba@1820
   432
      bool operator!=(const Edge i) const {return id!=i.id;}
deba@1820
   433
      bool operator<(const Edge i) const {return id<i.id;}
deba@1820
   434
    };
deba@1820
   435
deba@1820
   436
    void firstUpper(Node& node) const {
deba@1820
   437
      node.id = 2 * upperNodes.size() - 2;
deba@1820
   438
      if (node.id < 0) node.id = -1; 
deba@1820
   439
    }
deba@1820
   440
    void nextUpper(Node& node) const {
deba@1820
   441
      node.id -= 2;
deba@1820
   442
      if (node.id < 0) node.id = -1; 
deba@1820
   443
    }
deba@1820
   444
deba@1820
   445
    void firstLower(Node& node) const {
deba@1820
   446
      node.id = 2 * lowerNodes.size() - 1;
deba@1820
   447
    }
deba@1820
   448
    void nextLower(Node& node) const {
deba@1820
   449
      node.id -= 2;
deba@1820
   450
    }
deba@1820
   451
deba@1820
   452
    void first(Node& node) const {
deba@1820
   453
      if (upperNodes.size() > 0) {
deba@1820
   454
	node.id = 2 * upperNodes.size() - 2;
deba@1820
   455
      } else {
deba@1820
   456
	node.id = 2 * lowerNodes.size() - 1;
deba@1820
   457
      }
deba@1820
   458
    }
deba@1820
   459
    void next(Node& node) const {
deba@1820
   460
      node.id -= 2;
deba@1820
   461
      if (node.id == -2) {
deba@1820
   462
	node.id = 2 * lowerNodes.size() - 1;
deba@1820
   463
      }
deba@1820
   464
    }
deba@1820
   465
  
deba@1820
   466
    void first(Edge& edge) const {
deba@1820
   467
      edge.id = edges.size() - 1;
deba@1820
   468
    }
deba@1820
   469
    void next(Edge& edge) const {
deba@1820
   470
      --edge.id;
deba@1820
   471
    }
deba@1820
   472
deba@1820
   473
    void firstDown(Edge& edge, const Node& node) const {
deba@1820
   474
      LEMON_ASSERT((node.id & 1) == 0, NodeSetError());
deba@1820
   475
      edge.id = upperNodes[node.id >> 1].first;
deba@1820
   476
    }
deba@1820
   477
    void nextDown(Edge& edge) const {
deba@1820
   478
      edge.id = edges[edge.id].next_down;
deba@1820
   479
    }
deba@1820
   480
deba@1820
   481
    void firstUp(Edge& edge, const Node& node) const {
deba@1820
   482
      LEMON_ASSERT((node.id & 1) == 1, NodeSetError());
deba@1820
   483
      edge.id = lowerNodes[node.id >> 1].first;
deba@1820
   484
    }
deba@1820
   485
    void nextUp(Edge& edge) const {
deba@1820
   486
      edge.id = edges[edge.id].next_up;
deba@1820
   487
    }
deba@1820
   488
deba@1820
   489
    static int id(const Node& node) {
deba@1820
   490
      return node.id;
deba@1820
   491
    }
deba@1820
   492
    static Node nodeFromId(int id) {
deba@1820
   493
      return Node(id);
deba@1820
   494
    }
deba@1820
   495
    int maxNodeId() const {
deba@1820
   496
      return upperNodes.size() > lowerNodes.size() ?
deba@1820
   497
	upperNodes.size() * 2 - 2 : lowerNodes.size() * 2 - 1;
deba@1820
   498
    }
deba@1820
   499
  
deba@1820
   500
    static int id(const Edge& edge) {
deba@1820
   501
      return edge.id;
deba@1820
   502
    }
deba@1820
   503
    static Edge edgeFromId(int id) {
deba@1820
   504
      return Edge(id);
deba@1820
   505
    }
deba@1820
   506
    int maxEdgeId() const {
deba@1820
   507
      return edges.size();
deba@1820
   508
    }
deba@1820
   509
  
deba@1820
   510
    static int upperId(const Node& node) {
deba@1820
   511
      return node.id >> 1;
deba@1820
   512
    }
deba@1820
   513
    static Node fromUpperId(int id, Node) {
deba@1820
   514
      return Node(id << 1);
deba@1820
   515
    }
deba@1820
   516
    int maxUpperId() const {
deba@1820
   517
      return upperNodes.size();
deba@1820
   518
    }
deba@1820
   519
deba@1820
   520
    static int lowerId(const Node& node) {
deba@1820
   521
      return node.id >> 1;
deba@1820
   522
    }
deba@1820
   523
    static Node fromLowerId(int id) {
deba@1820
   524
      return Node((id << 1) + 1);
deba@1820
   525
    }
deba@1820
   526
    int maxLowerId() const {
deba@1820
   527
      return lowerNodes.size();
deba@1820
   528
    }
deba@1820
   529
deba@1820
   530
    Node upperNode(const Edge& edge) const {
deba@1820
   531
      return Node(edges[edge.id].upper);
deba@1820
   532
    }
deba@1820
   533
    Node lowerNode(const Edge& edge) const {
deba@1820
   534
      return Node(edges[edge.id].lower);
deba@1820
   535
    }
deba@1820
   536
deba@1820
   537
    static bool upper(const Node& node) {
deba@1820
   538
      return (node.id & 1) == 0;
deba@1820
   539
    }
deba@1820
   540
deba@1820
   541
    static bool lower(const Node& node) {
deba@1820
   542
      return (node.id & 1) == 1;
deba@1820
   543
    }
deba@1820
   544
deba@1820
   545
    Node addUpperNode() {
deba@1820
   546
      NodeT nodeT;
deba@1820
   547
      nodeT.first = -1;
deba@1820
   548
      upperNodes.push_back(nodeT);
deba@1820
   549
      return Node(upperNodes.size() * 2 - 2);
deba@1820
   550
    }
deba@1820
   551
deba@1820
   552
    Node addLowerNode() {
deba@1820
   553
      NodeT nodeT;
deba@1820
   554
      nodeT.first = -1;
deba@1820
   555
      lowerNodes.push_back(nodeT);
deba@1820
   556
      return Node(lowerNodes.size() * 2 - 1);
deba@1820
   557
    }
deba@1820
   558
deba@1820
   559
    Edge addEdge(const Node& source, const Node& target) {
deba@1820
   560
      LEMON_ASSERT(((source.id ^ target.id) & 1) == 1, NodeSetError());
deba@1820
   561
      EdgeT edgeT;
deba@1820
   562
      if ((source.id & 1) == 0) {
deba@1820
   563
	edgeT.upper = source.id;
deba@1820
   564
	edgeT.lower = target.id;
deba@1820
   565
      } else {
deba@1820
   566
	edgeT.upper = target.id;
deba@1820
   567
	edgeT.lower = source.id;
deba@1820
   568
      }
deba@1820
   569
      edgeT.next_down = upperNodes[edgeT.upper >> 1].first;
deba@1820
   570
      upperNodes[edgeT.upper >> 1].first = edges.size();
deba@1820
   571
      edgeT.next_up = lowerNodes[edgeT.lower >> 1].first;
deba@1820
   572
      lowerNodes[edgeT.lower >> 1].first = edges.size();
deba@1820
   573
      edges.push_back(edgeT);
deba@1820
   574
      return Edge(edges.size() - 1);
deba@1820
   575
    }
deba@1820
   576
deba@1820
   577
    void clear() {
deba@1820
   578
      upperNodes.clear();
deba@1820
   579
      lowerNodes.clear();
deba@1820
   580
      edges.clear();
deba@1820
   581
    }
deba@1820
   582
deba@1820
   583
  };
deba@1820
   584
deba@1820
   585
deba@1820
   586
  typedef ClearableUndirBipartiteGraphExtender<
deba@1820
   587
    ExtendableUndirBipartiteGraphExtender<
deba@1820
   588
    MappableUndirBipartiteGraphExtender<
deba@1820
   589
    IterableUndirBipartiteGraphExtender<
deba@1820
   590
    AlterableUndirBipartiteGraphExtender<
deba@1820
   591
    UndirBipartiteGraphExtender <
deba@1820
   592
    SmartUndirBipartiteGraphBase> > > > > >
deba@1820
   593
  ExtendedSmartUndirBipartiteGraphBase;
deba@1820
   594
deba@1820
   595
deba@1820
   596
  class SmartUndirBipartiteGraph : 
deba@1820
   597
    public ExtendedSmartUndirBipartiteGraphBase {
deba@1820
   598
  };
deba@1820
   599
alpar@950
   600
  
alpar@407
   601
  /// @}  
alpar@921
   602
} //namespace lemon
alpar@104
   603
alpar@157
   604
alpar@921
   605
#endif //LEMON_SMART_GRAPH_H