lemon/full_graph.h
author hegyi
Mon, 21 Nov 2005 18:03:20 +0000
changeset 1823 cb082cdf3667
parent 1791 62e7d237e1fb
child 1828 fd3771591a5c
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/full_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@591
    16
alpar@921
    17
#ifndef LEMON_FULL_GRAPH_H
alpar@921
    18
#define LEMON_FULL_GRAPH_H
alpar@591
    19
deba@983
    20
#include <cmath>
deba@983
    21
klao@946
    22
deba@1307
    23
#include <lemon/bits/iterable_graph_extender.h>
deba@1307
    24
#include <lemon/bits/alteration_notifier.h>
deba@1703
    25
#include <lemon/bits/static_map.h>
deba@1791
    26
#include <lemon/bits/graph_extender.h>
deba@1566
    27
klao@977
    28
#include <lemon/invalid.h>
klao@977
    29
#include <lemon/utility.h>
klao@977
    30
klao@977
    31
alpar@591
    32
///\ingroup graphs
alpar@591
    33
///\file
deba@1692
    34
///\brief FullGraph and UndirFullGraph classes.
alpar@591
    35
alpar@591
    36
alpar@921
    37
namespace lemon {
alpar@591
    38
klao@946
    39
  class FullGraphBase {
deba@1566
    40
    int _nodeNum;
deba@1566
    41
    int _edgeNum;
alpar@591
    42
  public:
deba@782
    43
klao@946
    44
    typedef FullGraphBase Graph;
alpar@591
    45
alpar@591
    46
    class Node;
alpar@591
    47
    class Edge;
deba@782
    48
alpar@591
    49
  public:
alpar@591
    50
klao@946
    51
    FullGraphBase() {}
klao@946
    52
klao@946
    53
alpar@591
    54
    ///Creates a full graph with \c n nodes.
deba@1566
    55
    void construct(int n) { _nodeNum = n; _edgeNum = n * n; }
alpar@591
    56
    ///
klao@946
    57
    //    FullGraphBase(const FullGraphBase &_g)
deba@1566
    58
    //      : _nodeNum(_g.nodeNum()), _edgeNum(_nodeNum*_nodeNum) { }
alpar@591
    59
    
klao@977
    60
    typedef True NodeNumTag;
klao@977
    61
    typedef True EdgeNumTag;
klao@977
    62
alpar@813
    63
    ///Number of nodes.
deba@1566
    64
    int nodeNum() const { return _nodeNum; }
alpar@813
    65
    ///Number of edges.
deba@1566
    66
    int edgeNum() const { return _edgeNum; }
alpar@591
    67
alpar@813
    68
    /// Maximum node ID.
alpar@813
    69
    
alpar@813
    70
    /// Maximum node ID.
alpar@813
    71
    ///\sa id(Node)
deba@1791
    72
    int maxNodeId() const { return _nodeNum-1; }
alpar@813
    73
    /// Maximum edge ID.
alpar@813
    74
    
alpar@813
    75
    /// Maximum edge ID.
alpar@813
    76
    ///\sa id(Edge)
deba@1791
    77
    int maxEdgeId() const { return _edgeNum-1; }
alpar@591
    78
deba@1566
    79
    Node source(Edge e) const { return e.id % _nodeNum; }
deba@1566
    80
    Node target(Edge e) const { return e.id / _nodeNum; }
alpar@591
    81
alpar@591
    82
alpar@813
    83
    /// Node ID.
alpar@813
    84
    
alpar@813
    85
    /// The ID of a valid Node is a nonnegative integer not greater than
alpar@813
    86
    /// \ref maxNodeId(). The range of the ID's is not surely continuous
alpar@813
    87
    /// and the greatest node ID can be actually less then \ref maxNodeId().
alpar@813
    88
    ///
alpar@813
    89
    /// The ID of the \ref INVALID node is -1.
alpar@813
    90
    ///\return The ID of the node \c v. 
klao@946
    91
klao@946
    92
    static int id(Node v) { return v.id; }
alpar@813
    93
    /// Edge ID.
alpar@813
    94
    
alpar@813
    95
    /// The ID of a valid Edge is a nonnegative integer not greater than
alpar@813
    96
    /// \ref maxEdgeId(). The range of the ID's is not surely continuous
alpar@813
    97
    /// and the greatest edge ID can be actually less then \ref maxEdgeId().
alpar@813
    98
    ///
alpar@813
    99
    /// The ID of the \ref INVALID edge is -1.
alpar@813
   100
    ///\return The ID of the edge \c e. 
klao@946
   101
    static int id(Edge e) { return e.id; }
alpar@591
   102
deba@1791
   103
    static Node nodeFromId(int id) { return Node(id);}
deba@1106
   104
    
deba@1791
   105
    static Edge edgeFromId(int id) { return Edge(id);}
deba@1106
   106
deba@1566
   107
    typedef True FindEdgeTag;
deba@1566
   108
alpar@774
   109
    /// Finds an edge between two nodes.
alpar@774
   110
    
alpar@774
   111
    /// Finds an edge from node \c u to node \c v.
alpar@774
   112
    ///
alpar@774
   113
    /// If \c prev is \ref INVALID (this is the default value), then
alpar@774
   114
    /// It finds the first edge from \c u to \c v. Otherwise it looks for
alpar@774
   115
    /// the next edge from \c u to \c v after \c prev.
alpar@774
   116
    /// \return The found edge or INVALID if there is no such an edge.
deba@1566
   117
    Edge findEdge(Node u,Node v, Edge prev = INVALID) const {
klao@946
   118
      return prev.id == -1 ? Edge(*this, u.id, v.id) : INVALID;
alpar@774
   119
    }
alpar@774
   120
    
alpar@774
   121
      
alpar@591
   122
    class Node {
klao@946
   123
      friend class FullGraphBase;
alpar@591
   124
alpar@591
   125
    protected:
klao@946
   126
      int id;
alpar@1643
   127
      Node(int _id) : id(_id) {}
alpar@591
   128
    public:
alpar@591
   129
      Node() {}
alpar@1643
   130
      Node (Invalid) : id(-1) {}
klao@946
   131
      bool operator==(const Node node) const {return id == node.id;}
klao@946
   132
      bool operator!=(const Node node) const {return id != node.id;}
klao@946
   133
      bool operator<(const Node node) const {return id < node.id;}
alpar@591
   134
    };
alpar@591
   135
    
klao@946
   136
klao@946
   137
klao@946
   138
    class Edge {
klao@946
   139
      friend class FullGraphBase;
klao@946
   140
      
klao@946
   141
    protected:
deba@1566
   142
      int id;  // _nodeNum * target + source;
klao@946
   143
klao@946
   144
      Edge(int _id) : id(_id) {}
klao@946
   145
alpar@986
   146
      Edge(const FullGraphBase& _graph, int source, int target) 
deba@1566
   147
	: id(_graph._nodeNum * target+source) {}
alpar@591
   148
    public:
klao@946
   149
      Edge() { }
klao@946
   150
      Edge (Invalid) { id = -1; }
klao@946
   151
      bool operator==(const Edge edge) const {return id == edge.id;}
klao@946
   152
      bool operator!=(const Edge edge) const {return id != edge.id;}
klao@946
   153
      bool operator<(const Edge edge) const {return id < edge.id;}
alpar@591
   154
    };
alpar@591
   155
klao@946
   156
    void first(Node& node) const {
deba@1566
   157
      node.id = _nodeNum-1;
klao@946
   158
    }
alpar@591
   159
klao@946
   160
    static void next(Node& node) {
klao@946
   161
      --node.id;
klao@946
   162
    }
klao@946
   163
klao@946
   164
    void first(Edge& edge) const {
deba@1566
   165
      edge.id = _edgeNum-1;
klao@946
   166
    }
klao@946
   167
klao@946
   168
    static void next(Edge& edge) {
klao@946
   169
      --edge.id;
klao@946
   170
    }
klao@946
   171
klao@946
   172
    void firstOut(Edge& edge, const Node& node) const {
deba@1566
   173
      edge.id = _edgeNum + node.id - _nodeNum;
klao@946
   174
    }
klao@946
   175
klao@946
   176
    void nextOut(Edge& edge) const {
deba@1566
   177
      edge.id -= _nodeNum;
klao@946
   178
      if (edge.id < 0) edge.id = -1;
klao@946
   179
    }
klao@946
   180
klao@946
   181
    void firstIn(Edge& edge, const Node& node) const {
deba@1566
   182
      edge.id = node.id * _nodeNum;
klao@946
   183
    }
alpar@591
   184
    
klao@946
   185
    void nextIn(Edge& edge) const {
klao@946
   186
      ++edge.id;
deba@1566
   187
      if (edge.id % _nodeNum == 0) edge.id = -1;
klao@946
   188
    }
alpar@591
   189
alpar@591
   190
  };
alpar@591
   191
deba@1703
   192
  typedef StaticMappableGraphExtender<
deba@1669
   193
    IterableGraphExtender<
deba@1791
   194
    AlterableGraphExtender<
deba@1791
   195
    GraphExtender<FullGraphBase> > > > ExtendedFullGraphBase;
klao@946
   196
deba@1566
   197
  /// \ingroup graphs
alpar@951
   198
  ///
deba@1566
   199
  /// \brief A full graph class.
deba@1566
   200
  ///
deba@1566
   201
  /// This is a simple and fast directed full graph implementation.
deba@1566
   202
  /// It is completely static, so you can neither add nor delete either
deba@1566
   203
  /// edges or nodes.
deba@1566
   204
  /// Thus it conforms to
deba@1566
   205
  /// the \ref concept::StaticGraph "StaticGraph" concept
deba@1566
   206
  /// \sa concept::StaticGraph.
deba@1566
   207
  ///
deba@1566
   208
  /// \author Alpar Juttner
deba@1669
   209
  class FullGraph : public ExtendedFullGraphBase {
klao@946
   210
  public:
klao@946
   211
klao@946
   212
    FullGraph(int n) { construct(n); }
klao@946
   213
  };
klao@946
   214
deba@983
   215
deba@983
   216
  class UndirFullGraphBase {
deba@1566
   217
    int _nodeNum;
deba@1566
   218
    int _edgeNum;
deba@983
   219
  public:
deba@983
   220
deba@984
   221
    typedef UndirFullGraphBase Graph;
deba@983
   222
deba@983
   223
    class Node;
deba@983
   224
    class Edge;
deba@983
   225
deba@983
   226
  public:
deba@983
   227
deba@984
   228
    UndirFullGraphBase() {}
deba@983
   229
deba@983
   230
deba@983
   231
    ///Creates a full graph with \c n nodes.
deba@1566
   232
    void construct(int n) { _nodeNum = n; _edgeNum = n * (n - 1) / 2; }
deba@983
   233
    ///
deba@983
   234
    //    FullGraphBase(const FullGraphBase &_g)
deba@1566
   235
    //      : _nodeNum(_g.nodeNum()), _edgeNum(_nodeNum*_nodeNum) { }
deba@983
   236
    
deba@983
   237
    typedef True NodeNumTag;
deba@983
   238
    typedef True EdgeNumTag;
deba@983
   239
deba@983
   240
    ///Number of nodes.
deba@1566
   241
    int nodeNum() const { return _nodeNum; }
deba@983
   242
    ///Number of edges.
deba@1566
   243
    int edgeNum() const { return _edgeNum; }
deba@983
   244
deba@983
   245
    /// Maximum node ID.
deba@983
   246
    
deba@983
   247
    /// Maximum node ID.
deba@983
   248
    ///\sa id(Node)
deba@1791
   249
    int maxNodeId() const { return _nodeNum-1; }
deba@983
   250
    /// Maximum edge ID.
deba@983
   251
    
deba@983
   252
    /// Maximum edge ID.
deba@983
   253
    ///\sa id(Edge)
deba@1791
   254
    int maxEdgeId() const { return _edgeNum-1; }
deba@983
   255
alpar@986
   256
    Node source(Edge e) const { 
deba@983
   257
      /// \todo we may do it faster
alpar@1643
   258
      return Node(((int)sqrt((double)(1 + 8 * e.id)) + 1) / 2);
deba@983
   259
    }
deba@983
   260
alpar@986
   261
    Node target(Edge e) const { 
alpar@986
   262
      int source = ((int)sqrt((double)(1 + 8 * e.id)) + 1) / 2;;
alpar@1643
   263
      return Node(e.id - (source) * (source - 1) / 2);
deba@983
   264
    }
deba@983
   265
deba@983
   266
deba@983
   267
    /// Node ID.
deba@983
   268
    
deba@983
   269
    /// The ID of a valid Node is a nonnegative integer not greater than
deba@983
   270
    /// \ref maxNodeId(). The range of the ID's is not surely continuous
deba@983
   271
    /// and the greatest node ID can be actually less then \ref maxNodeId().
deba@983
   272
    ///
deba@983
   273
    /// The ID of the \ref INVALID node is -1.
deba@983
   274
    ///\return The ID of the node \c v. 
deba@983
   275
deba@983
   276
    static int id(Node v) { return v.id; }
deba@983
   277
    /// Edge ID.
deba@983
   278
    
deba@983
   279
    /// The ID of a valid Edge is a nonnegative integer not greater than
deba@983
   280
    /// \ref maxEdgeId(). The range of the ID's is not surely continuous
deba@983
   281
    /// and the greatest edge ID can be actually less then \ref maxEdgeId().
deba@983
   282
    ///
deba@983
   283
    /// The ID of the \ref INVALID edge is -1.
deba@983
   284
    ///\return The ID of the edge \c e. 
deba@983
   285
    static int id(Edge e) { return e.id; }
deba@983
   286
deba@983
   287
    /// Finds an edge between two nodes.
deba@983
   288
    
deba@983
   289
    /// Finds an edge from node \c u to node \c v.
deba@983
   290
    ///
deba@983
   291
    /// If \c prev is \ref INVALID (this is the default value), then
deba@983
   292
    /// It finds the first edge from \c u to \c v. Otherwise it looks for
deba@983
   293
    /// the next edge from \c u to \c v after \c prev.
deba@983
   294
    /// \return The found edge or INVALID if there is no such an edge.
deba@1703
   295
    Edge findEdge(Node u, Node v, Edge prev = INVALID) const {
deba@1703
   296
      if (prev.id != -1 || u.id <= v.id) return -1;
deba@1703
   297
      return Edge(u.id * (u.id - 1) / 2 + v.id);
deba@983
   298
    }
deba@1703
   299
deba@1703
   300
    typedef True FindEdgeTag;
deba@983
   301
    
deba@983
   302
      
deba@983
   303
    class Node {
alpar@985
   304
      friend class UndirFullGraphBase;
deba@983
   305
deba@983
   306
    protected:
deba@983
   307
      int id;
deba@983
   308
      Node(int _id) { id = _id;}
deba@983
   309
    public:
deba@983
   310
      Node() {}
deba@983
   311
      Node (Invalid) { id = -1; }
deba@983
   312
      bool operator==(const Node node) const {return id == node.id;}
deba@983
   313
      bool operator!=(const Node node) const {return id != node.id;}
deba@983
   314
      bool operator<(const Node node) const {return id < node.id;}
deba@983
   315
    };
deba@983
   316
    
deba@983
   317
deba@983
   318
deba@983
   319
    class Edge {
alpar@985
   320
      friend class UndirFullGraphBase;
deba@983
   321
      
deba@983
   322
    protected:
deba@1566
   323
      int id;  // _nodeNum * target + source;
deba@983
   324
deba@983
   325
      Edge(int _id) : id(_id) {}
deba@983
   326
deba@983
   327
    public:
deba@983
   328
      Edge() { }
deba@983
   329
      Edge (Invalid) { id = -1; }
deba@983
   330
      bool operator==(const Edge edge) const {return id == edge.id;}
deba@983
   331
      bool operator!=(const Edge edge) const {return id != edge.id;}
deba@983
   332
      bool operator<(const Edge edge) const {return id < edge.id;}
deba@983
   333
    };
deba@983
   334
deba@983
   335
    void first(Node& node) const {
deba@1703
   336
      node.id = _nodeNum - 1;
deba@983
   337
    }
deba@983
   338
deba@983
   339
    static void next(Node& node) {
deba@983
   340
      --node.id;
deba@983
   341
    }
deba@983
   342
deba@983
   343
    void first(Edge& edge) const {
deba@1703
   344
      edge.id = _edgeNum - 1;
deba@983
   345
    }
deba@983
   346
deba@983
   347
    static void next(Edge& edge) {
deba@983
   348
      --edge.id;
deba@983
   349
    }
deba@983
   350
deba@983
   351
    void firstOut(Edge& edge, const Node& node) const {      
deba@1703
   352
      int src = node.id;
deba@1703
   353
      int trg = 0;
deba@1703
   354
      edge.id = (trg < src ? src * (src - 1) / 2 + trg : -1);
deba@983
   355
    }
deba@983
   356
deba@983
   357
    /// \todo with specialized iterators we can make faster iterating
deba@1703
   358
    void nextOut(Edge& edge) const {
deba@1703
   359
      int src = source(edge).id;
deba@1703
   360
      int trg = target(edge).id;
deba@1703
   361
      ++trg;
deba@1703
   362
      edge.id = (trg < src ? src * (src - 1) / 2 + trg : -1);
deba@983
   363
    }
deba@983
   364
deba@983
   365
    void firstIn(Edge& edge, const Node& node) const {
deba@1703
   366
      int src = node.id + 1;
deba@1703
   367
      int trg = node.id;
deba@1703
   368
      edge.id = (src < _nodeNum ? src * (src - 1) / 2 + trg : -1);
deba@983
   369
    }
deba@983
   370
    
deba@1703
   371
    void nextIn(Edge& edge) const {
deba@1703
   372
      int src = source(edge).id;
deba@1703
   373
      int trg = target(edge).id;
deba@1703
   374
      ++src;
deba@1703
   375
      edge.id = (src < _nodeNum ? src * (src - 1) / 2 + trg : -1);
deba@983
   376
    }
deba@983
   377
deba@983
   378
  };
deba@983
   379
deba@1703
   380
  typedef StaticMappableUndirGraphExtender<
deba@1669
   381
    IterableUndirGraphExtender<
deba@1669
   382
    AlterableUndirGraphExtender<
deba@1669
   383
    UndirGraphExtender<UndirFullGraphBase> > > > ExtendedUndirFullGraphBase;
alpar@1555
   384
deba@1566
   385
  /// \ingroup graphs
deba@1566
   386
  ///
deba@1566
   387
  /// \brief An undirected full graph class.
deba@1566
   388
  ///
deba@1726
   389
  /// This is a simple and fast undirected full graph implementation.
deba@1566
   390
  /// It is completely static, so you can neither add nor delete either
deba@1566
   391
  /// edges or nodes.
deba@1566
   392
  ///
deba@1566
   393
  /// The main difference beetween the \e FullGraph and \e UndirFullGraph class
deba@1566
   394
  /// is that this class conforms to the undirected graph concept and
deba@1726
   395
  /// it does not contain the loop edges.
deba@1566
   396
  ///
deba@1566
   397
  /// \sa FullGraph
deba@1566
   398
  ///
deba@1566
   399
  /// \author Balazs Dezso
deba@1669
   400
  class UndirFullGraph : public ExtendedUndirFullGraphBase {
deba@1566
   401
  public:
deba@1566
   402
    UndirFullGraph(int n) { construct(n); }
deba@1566
   403
  };
alpar@591
   404
deba@1820
   405
deba@1820
   406
  class FullUndirBipartiteGraphBase {
deba@1820
   407
  protected:
deba@1820
   408
deba@1820
   409
    int _upperNodeNum;
deba@1820
   410
    int _lowerNodeNum;
deba@1820
   411
deba@1820
   412
    int _edgeNum;
deba@1820
   413
deba@1820
   414
  public:
deba@1820
   415
deba@1820
   416
    class NodeSetError : public LogicError {
deba@1820
   417
      virtual const char* exceptionName() const { 
deba@1820
   418
	return "lemon::FullUndirBipartiteGraph::NodeSetError";
deba@1820
   419
      }
deba@1820
   420
    };
deba@1820
   421
  
deba@1820
   422
    class Node {
deba@1820
   423
      friend class FullUndirBipartiteGraphBase;
deba@1820
   424
    protected:
deba@1820
   425
      int id;
deba@1820
   426
deba@1820
   427
      Node(int _id) : id(_id) {}
deba@1820
   428
    public:
deba@1820
   429
      Node() {}
deba@1820
   430
      Node(Invalid) { id = -1; }
deba@1820
   431
      bool operator==(const Node i) const {return id==i.id;}
deba@1820
   432
      bool operator!=(const Node i) const {return id!=i.id;}
deba@1820
   433
      bool operator<(const Node i) const {return id<i.id;}
deba@1820
   434
    };
deba@1820
   435
deba@1820
   436
    class Edge {
deba@1820
   437
      friend class FullUndirBipartiteGraphBase;
deba@1820
   438
    protected:
deba@1820
   439
      int id;
deba@1820
   440
deba@1820
   441
      Edge(int _id) { id = _id;}
deba@1820
   442
    public:
deba@1820
   443
      Edge() {}
deba@1820
   444
      Edge (Invalid) { id = -1; }
deba@1820
   445
      bool operator==(const Edge i) const {return id==i.id;}
deba@1820
   446
      bool operator!=(const Edge i) const {return id!=i.id;}
deba@1820
   447
      bool operator<(const Edge i) const {return id<i.id;}
deba@1820
   448
    };
deba@1820
   449
deba@1820
   450
    void construct(int upperNodeNum, int lowerNodeNum) {
deba@1820
   451
      _upperNodeNum = upperNodeNum;
deba@1820
   452
      _lowerNodeNum = lowerNodeNum;
deba@1820
   453
      _edgeNum = upperNodeNum * lowerNodeNum;
deba@1820
   454
    }
deba@1820
   455
deba@1820
   456
    void firstUpper(Node& node) const {
deba@1820
   457
      node.id = 2 * _upperNodeNum - 2;
deba@1820
   458
      if (node.id < 0) node.id = -1; 
deba@1820
   459
    }
deba@1820
   460
    void nextUpper(Node& node) const {
deba@1820
   461
      node.id -= 2;
deba@1820
   462
      if (node.id < 0) node.id = -1; 
deba@1820
   463
    }
deba@1820
   464
deba@1820
   465
    void firstLower(Node& node) const {
deba@1820
   466
      node.id = 2 * _lowerNodeNum - 1;
deba@1820
   467
    }
deba@1820
   468
    void nextLower(Node& node) const {
deba@1820
   469
      node.id -= 2;
deba@1820
   470
    }
deba@1820
   471
deba@1820
   472
    void first(Node& node) const {
deba@1820
   473
      if (_upperNodeNum > 0) {
deba@1820
   474
	node.id = 2 * _upperNodeNum - 2;
deba@1820
   475
      } else {
deba@1820
   476
	node.id = 2 * _lowerNodeNum - 1;
deba@1820
   477
      }
deba@1820
   478
    }
deba@1820
   479
    void next(Node& node) const {
deba@1820
   480
      node.id -= 2;
deba@1820
   481
      if (node.id == -2) {
deba@1820
   482
	node.id = 2 * _lowerNodeNum - 1;
deba@1820
   483
      }
deba@1820
   484
    }
deba@1820
   485
  
deba@1820
   486
    void first(Edge& edge) const {
deba@1820
   487
      edge.id = _edgeNum - 1;
deba@1820
   488
    }
deba@1820
   489
    void next(Edge& edge) const {
deba@1820
   490
      --edge.id;
deba@1820
   491
    }
deba@1820
   492
deba@1820
   493
    void firstDown(Edge& edge, const Node& node) const {
deba@1820
   494
      LEMON_ASSERT((node.id & 1) == 0, NodeSetError());
deba@1820
   495
      edge.id = (node.id >> 1) * _lowerNodeNum;
deba@1820
   496
    }
deba@1820
   497
    void nextDown(Edge& edge) const {
deba@1820
   498
      ++(edge.id);
deba@1820
   499
      if (edge.id % _lowerNodeNum == 0) edge.id = -1;
deba@1820
   500
    }
deba@1820
   501
deba@1820
   502
    void firstUp(Edge& edge, const Node& node) const {
deba@1820
   503
      LEMON_ASSERT((node.id & 1) == 1, NodeSetError());
deba@1820
   504
      edge.id = (node.id >> 1);
deba@1820
   505
    }
deba@1820
   506
    void nextUp(Edge& edge) const {
deba@1820
   507
      edge.id += _lowerNodeNum;
deba@1820
   508
      if (edge.id >= _edgeNum) edge.id = -1;
deba@1820
   509
    }
deba@1820
   510
deba@1820
   511
    static int id(const Node& node) {
deba@1820
   512
      return node.id;
deba@1820
   513
    }
deba@1820
   514
    static Node nodeFromId(int id) {
deba@1820
   515
      return Node(id);
deba@1820
   516
    }
deba@1820
   517
    int maxNodeId() const {
deba@1820
   518
      return _upperNodeNum > _lowerNodeNum ? 
deba@1820
   519
	_upperNodeNum * 2 - 2 : _lowerNodeNum * 2 - 1;
deba@1820
   520
    }
deba@1820
   521
  
deba@1820
   522
    static int id(const Edge& edge) {
deba@1820
   523
      return edge.id;
deba@1820
   524
    }
deba@1820
   525
    static Edge edgeFromId(int id) {
deba@1820
   526
      return Edge(id);
deba@1820
   527
    }
deba@1820
   528
    int maxEdgeId() const {
deba@1820
   529
      return _edgeNum - 1;
deba@1820
   530
    }
deba@1820
   531
  
deba@1820
   532
    static int upperId(const Node& node) {
deba@1820
   533
      return node.id >> 1;
deba@1820
   534
    }
deba@1820
   535
    static Node fromUpperId(int id, Node) {
deba@1820
   536
      return Node(id << 1);
deba@1820
   537
    }
deba@1820
   538
    int maxUpperId() const {
deba@1820
   539
      return _upperNodeNum;
deba@1820
   540
    }
deba@1820
   541
deba@1820
   542
    static int lowerId(const Node& node) {
deba@1820
   543
      return node.id >> 1;
deba@1820
   544
    }
deba@1820
   545
    static Node fromLowerId(int id) {
deba@1820
   546
      return Node((id << 1) + 1);
deba@1820
   547
    }
deba@1820
   548
    int maxLowerId() const {
deba@1820
   549
      return _lowerNodeNum;
deba@1820
   550
    }
deba@1820
   551
deba@1820
   552
    Node upperNode(const Edge& edge) const {
deba@1820
   553
      return Node((edge.id / _lowerNodeNum) << 1);
deba@1820
   554
    }
deba@1820
   555
    Node lowerNode(const Edge& edge) const {
deba@1820
   556
      return Node(((edge.id % _lowerNodeNum) << 1) + 1);
deba@1820
   557
    }
deba@1820
   558
deba@1820
   559
    static bool upper(const Node& node) {
deba@1820
   560
      return (node.id & 1) == 0;
deba@1820
   561
    }
deba@1820
   562
deba@1820
   563
    static bool lower(const Node& node) {
deba@1820
   564
      return (node.id & 1) == 1;
deba@1820
   565
    }
deba@1820
   566
deba@1820
   567
    static Node upperNode(int index) {
deba@1820
   568
      return Node(index << 1);
deba@1820
   569
    }
deba@1820
   570
deba@1820
   571
    static Node lowerNode(int index) {
deba@1820
   572
      return Node((index << 1) + 1);
deba@1820
   573
    }
deba@1820
   574
deba@1820
   575
  };
deba@1820
   576
deba@1820
   577
deba@1820
   578
  typedef MappableUndirBipartiteGraphExtender<
deba@1820
   579
    IterableUndirBipartiteGraphExtender<
deba@1820
   580
    AlterableUndirBipartiteGraphExtender<
deba@1820
   581
    UndirBipartiteGraphExtender <
deba@1820
   582
    FullUndirBipartiteGraphBase> > > >
deba@1820
   583
  ExtendedFullUndirBipartiteGraphBase;
deba@1820
   584
deba@1820
   585
deba@1820
   586
  class FullUndirBipartiteGraph : 
deba@1820
   587
    public ExtendedFullUndirBipartiteGraphBase {
deba@1820
   588
  public:
deba@1820
   589
    typedef ExtendedFullUndirBipartiteGraphBase Parent;
deba@1820
   590
    FullUndirBipartiteGraph(int upperNodeNum, int lowerNodeNum) {
deba@1820
   591
      Parent::construct(upperNodeNum, lowerNodeNum);
deba@1820
   592
    }
deba@1820
   593
  };
deba@1820
   594
alpar@921
   595
} //namespace lemon
alpar@591
   596
alpar@591
   597
alpar@921
   598
#endif //LEMON_FULL_GRAPH_H