lemon/full_graph.h
author deba
Tue, 17 Oct 2006 10:50:57 +0000
changeset 2247 269a0dcee70b
parent 2223 590c1b663a27
child 2256 b22dfb6c5ff3
permissions -rw-r--r--
Update the Path concept
Concept check for paths

DirPath renamed to Path
The interface updated to the new lemon interface
Make difference between the empty path and the path from one node
Builder interface have not been changed
// I wanted but there was not accordance about it

UPath is removed
It was a buggy implementation, it could not iterate on the
nodes in the right order
Right way to use undirected paths => path of edges in undirected graphs

The tests have been modified to the current implementation
alpar@906
     1
/* -*- C++ -*-
alpar@906
     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@906
     8
 *
alpar@906
     9
 * Permission to use, modify and distribute this software is granted
alpar@906
    10
 * provided that this copyright notice appears in all copies. For
alpar@906
    11
 * precise terms see the accompanying LICENSE file.
alpar@906
    12
 *
alpar@906
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@906
    14
 * express or implied, and with no claim as to its suitability for any
alpar@906
    15
 * purpose.
alpar@906
    16
 *
alpar@906
    17
 */
alpar@591
    18
alpar@921
    19
#ifndef LEMON_FULL_GRAPH_H
alpar@921
    20
#define LEMON_FULL_GRAPH_H
alpar@591
    21
deba@983
    22
#include <cmath>
deba@983
    23
deba@2116
    24
#include <lemon/bits/base_extender.h>
deba@1791
    25
#include <lemon/bits/graph_extender.h>
deba@1566
    26
deba@1993
    27
#include <lemon/bits/invalid.h>
deba@1993
    28
#include <lemon/bits/utility.h>
klao@977
    29
klao@977
    30
alpar@591
    31
///\ingroup graphs
alpar@591
    32
///\file
deba@2116
    33
///\brief FullGraph and FullUGraph classes.
alpar@591
    34
alpar@591
    35
alpar@921
    36
namespace lemon {
alpar@591
    37
klao@946
    38
  class FullGraphBase {
deba@1566
    39
    int _nodeNum;
deba@1566
    40
    int _edgeNum;
alpar@591
    41
  public:
deba@782
    42
klao@946
    43
    typedef FullGraphBase Graph;
alpar@591
    44
alpar@591
    45
    class Node;
alpar@591
    46
    class Edge;
deba@782
    47
deba@2223
    48
  protected:
alpar@591
    49
klao@946
    50
    FullGraphBase() {}
klao@946
    51
deba@2223
    52
    void construct(int n) { _nodeNum = n; _edgeNum = n * n; }
klao@946
    53
deba@2223
    54
  public:
alpar@591
    55
    
klao@977
    56
    typedef True NodeNumTag;
klao@977
    57
    typedef True EdgeNumTag;
klao@977
    58
deba@1986
    59
    Node operator()(int index) const { return Node(index); }
deba@1986
    60
    int index(const Node& node) const { return node.id; }
deba@1986
    61
deba@2223
    62
    Edge edge(const Node& u, const Node& v) const { 
deba@2223
    63
      return Edge(*this, u.id, v.id); 
deba@2223
    64
    }
deba@2223
    65
deba@1566
    66
    int nodeNum() const { return _nodeNum; }
deba@1566
    67
    int edgeNum() const { return _edgeNum; }
alpar@591
    68
deba@1791
    69
    int maxNodeId() const { return _nodeNum-1; }
deba@1791
    70
    int maxEdgeId() const { return _edgeNum-1; }
alpar@591
    71
deba@1566
    72
    Node source(Edge e) const { return e.id % _nodeNum; }
deba@1566
    73
    Node target(Edge e) const { return e.id / _nodeNum; }
alpar@591
    74
alpar@591
    75
klao@946
    76
    static int id(Node v) { return v.id; }
klao@946
    77
    static int id(Edge e) { return e.id; }
alpar@591
    78
deba@1791
    79
    static Node nodeFromId(int id) { return Node(id);}
deba@1106
    80
    
deba@1791
    81
    static Edge edgeFromId(int id) { return Edge(id);}
deba@1106
    82
deba@1566
    83
    typedef True FindEdgeTag;
deba@1566
    84
deba@1566
    85
    Edge findEdge(Node u,Node v, Edge prev = INVALID) const {
klao@946
    86
      return prev.id == -1 ? Edge(*this, u.id, v.id) : INVALID;
alpar@774
    87
    }
alpar@774
    88
    
alpar@774
    89
      
alpar@591
    90
    class Node {
klao@946
    91
      friend class FullGraphBase;
alpar@591
    92
alpar@591
    93
    protected:
klao@946
    94
      int id;
alpar@1643
    95
      Node(int _id) : id(_id) {}
alpar@591
    96
    public:
alpar@591
    97
      Node() {}
alpar@1643
    98
      Node (Invalid) : id(-1) {}
klao@946
    99
      bool operator==(const Node node) const {return id == node.id;}
klao@946
   100
      bool operator!=(const Node node) const {return id != node.id;}
klao@946
   101
      bool operator<(const Node node) const {return id < node.id;}
alpar@591
   102
    };
alpar@591
   103
    
klao@946
   104
klao@946
   105
klao@946
   106
    class Edge {
klao@946
   107
      friend class FullGraphBase;
klao@946
   108
      
klao@946
   109
    protected:
deba@1566
   110
      int id;  // _nodeNum * target + source;
klao@946
   111
klao@946
   112
      Edge(int _id) : id(_id) {}
klao@946
   113
alpar@986
   114
      Edge(const FullGraphBase& _graph, int source, int target) 
deba@1566
   115
	: id(_graph._nodeNum * target+source) {}
alpar@591
   116
    public:
klao@946
   117
      Edge() { }
klao@946
   118
      Edge (Invalid) { id = -1; }
klao@946
   119
      bool operator==(const Edge edge) const {return id == edge.id;}
klao@946
   120
      bool operator!=(const Edge edge) const {return id != edge.id;}
klao@946
   121
      bool operator<(const Edge edge) const {return id < edge.id;}
alpar@591
   122
    };
alpar@591
   123
klao@946
   124
    void first(Node& node) const {
deba@1566
   125
      node.id = _nodeNum-1;
klao@946
   126
    }
alpar@591
   127
klao@946
   128
    static void next(Node& node) {
klao@946
   129
      --node.id;
klao@946
   130
    }
klao@946
   131
klao@946
   132
    void first(Edge& edge) const {
deba@1566
   133
      edge.id = _edgeNum-1;
klao@946
   134
    }
klao@946
   135
klao@946
   136
    static void next(Edge& edge) {
klao@946
   137
      --edge.id;
klao@946
   138
    }
klao@946
   139
klao@946
   140
    void firstOut(Edge& edge, const Node& node) const {
deba@1566
   141
      edge.id = _edgeNum + node.id - _nodeNum;
klao@946
   142
    }
klao@946
   143
klao@946
   144
    void nextOut(Edge& edge) const {
deba@1566
   145
      edge.id -= _nodeNum;
klao@946
   146
      if (edge.id < 0) edge.id = -1;
klao@946
   147
    }
klao@946
   148
klao@946
   149
    void firstIn(Edge& edge, const Node& node) const {
deba@1566
   150
      edge.id = node.id * _nodeNum;
klao@946
   151
    }
alpar@591
   152
    
klao@946
   153
    void nextIn(Edge& edge) const {
klao@946
   154
      ++edge.id;
deba@1566
   155
      if (edge.id % _nodeNum == 0) edge.id = -1;
klao@946
   156
    }
alpar@591
   157
alpar@591
   158
  };
alpar@591
   159
deba@1979
   160
  typedef GraphExtender<FullGraphBase> ExtendedFullGraphBase;
klao@946
   161
deba@1566
   162
  /// \ingroup graphs
alpar@951
   163
  ///
deba@1566
   164
  /// \brief A full graph class.
deba@1566
   165
  ///
deba@1566
   166
  /// This is a simple and fast directed full graph implementation.
deba@1566
   167
  /// It is completely static, so you can neither add nor delete either
deba@1566
   168
  /// edges or nodes.
deba@1566
   169
  /// Thus it conforms to
deba@2111
   170
  /// the \ref concept::Graph "Graph" concept
deba@2111
   171
  /// \sa concept::Graph.
deba@1566
   172
  ///
deba@1986
   173
  /// \sa FullUGraph
deba@1986
   174
  ///
deba@1566
   175
  /// \author Alpar Juttner
deba@1669
   176
  class FullGraph : public ExtendedFullGraphBase {
klao@946
   177
  public:
klao@946
   178
deba@1979
   179
    typedef ExtendedFullGraphBase Parent;
deba@1979
   180
deba@1979
   181
    /// \brief Constructor
deba@1987
   182
    FullGraph() { construct(0); }
deba@1987
   183
deba@1987
   184
    /// \brief Constructor
deba@1979
   185
    ///
klao@946
   186
    FullGraph(int n) { construct(n); }
deba@1979
   187
deba@1979
   188
    /// \brief Resize the graph
deba@1979
   189
    ///
deba@1986
   190
    /// Resize the graph. The function will fully destroy and build the graph.
deba@1986
   191
    /// This cause that the maps of the graph will reallocated
deba@1986
   192
    /// automatically and the previous values will be lost.
deba@1979
   193
    void resize(int n) {
deba@1979
   194
      Parent::getNotifier(Edge()).clear();
deba@1979
   195
      Parent::getNotifier(Node()).clear();
deba@1979
   196
      construct(n);
deba@1979
   197
      Parent::getNotifier(Node()).build();
deba@1979
   198
      Parent::getNotifier(Edge()).build();
deba@1979
   199
    }
deba@2223
   200
deba@2223
   201
    /// \brief Returns the node with the given index.
deba@2223
   202
    ///
deba@2223
   203
    /// Returns the node with the given index. Because it is a
deba@2223
   204
    /// static size graph the node's of the graph can be indiced
deba@2223
   205
    /// by the range from 0 to \e nodeNum()-1 and the index of
deba@2223
   206
    /// the node can accessed by the \e index() member.
deba@2223
   207
    Node operator()(int index) const { return Parent::operator()(index); }
deba@2223
   208
deba@2223
   209
    /// \brief Returns the index of the node.
deba@2223
   210
    ///
deba@2223
   211
    /// Returns the index of the node. Because it is a
deba@2223
   212
    /// static size graph the node's of the graph can be indiced
deba@2223
   213
    /// by the range from 0 to \e nodeNum()-1 and the index of
deba@2223
   214
    /// the node can accessed by the \e index() member.
deba@2223
   215
    int index(const Node& node) const { return Parent::index(node); }
deba@2223
   216
deba@2223
   217
    /// \brief Returns the edge connects the given nodes.
deba@2223
   218
    ///
deba@2223
   219
    /// Returns the edge connects the given nodes.
deba@2223
   220
    Edge edge(const Node& u, const Node& v) const { 
deba@2223
   221
      return Parent::edge(u, v); 
deba@2223
   222
    }
deba@2223
   223
deba@2223
   224
    /// \brief Number of nodes.
deba@2223
   225
    int nodeNum() const { return Parent::nodeNum(); }
deba@2223
   226
    /// \brief Number of edges.
deba@2223
   227
    int edgeNum() const { return Parent::edgeNum(); }
klao@946
   228
  };
klao@946
   229
deba@2116
   230
deba@2116
   231
  class FullUGraphBase {
deba@2116
   232
    int _nodeNum;
deba@2116
   233
    int _edgeNum;
deba@2116
   234
  public:
deba@2116
   235
deba@2116
   236
    typedef FullUGraphBase Graph;
deba@2116
   237
deba@2116
   238
    class Node;
deba@2116
   239
    class Edge;
deba@2116
   240
deba@2223
   241
  protected:
deba@2116
   242
deba@2116
   243
    FullUGraphBase() {}
deba@2116
   244
deba@2116
   245
    void construct(int n) { _nodeNum = n; _edgeNum = n * (n - 1) / 2; }
deba@2116
   246
deba@2223
   247
  public:
deba@2223
   248
deba@2223
   249
deba@2116
   250
    Node operator()(int index) const { return Node(index); }
deba@2223
   251
    int index(const Node& node) const { return node.id; }
deba@2116
   252
deba@2223
   253
    Edge edge(const Node& u, const Node& v) const { 
deba@2223
   254
      return Edge(u.id * (u.id - 1) / 2 + v.id);
deba@2223
   255
    }
deba@2116
   256
deba@2116
   257
    typedef True NodeNumTag;
deba@2116
   258
    typedef True EdgeNumTag;
deba@2116
   259
deba@2116
   260
    int nodeNum() const { return _nodeNum; }
deba@2116
   261
    int edgeNum() const { return _edgeNum; }
deba@2116
   262
deba@2116
   263
    int maxNodeId() const { return _nodeNum-1; }
deba@2116
   264
    int maxEdgeId() const { return _edgeNum-1; }
deba@2116
   265
deba@2116
   266
    static Node nodeFromId(int id) { return Node(id);}
deba@2116
   267
    static Edge edgeFromId(int id) { return Edge(id);}
deba@2116
   268
deba@2116
   269
    Node source(Edge e) const { 
deba@2116
   270
      /// \todo we may do it faster
deba@2116
   271
      return Node(((int)sqrt((double)(1 + 8 * e.id)) + 1) / 2);
deba@2116
   272
    }
deba@2116
   273
deba@2116
   274
    Node target(Edge e) const { 
deba@2116
   275
      int source = ((int)sqrt((double)(1 + 8 * e.id)) + 1) / 2;;
deba@2116
   276
      return Node(e.id - (source) * (source - 1) / 2);
deba@2116
   277
    }
deba@2116
   278
deba@2116
   279
    static int id(Node v) { return v.id; }
deba@2116
   280
    static int id(Edge e) { return e.id; }
deba@2116
   281
deba@2116
   282
    Edge findEdge(Node u, Node v, Edge prev = INVALID) const {
deba@2116
   283
      if (prev.id != -1 || u.id <= v.id) return Edge(-1);
deba@2116
   284
      return Edge(u.id * (u.id - 1) / 2 + v.id);
deba@2116
   285
    }
deba@2116
   286
deba@2116
   287
    typedef True FindEdgeTag;
deba@2116
   288
    
deba@2116
   289
      
deba@2116
   290
    class Node {
deba@2116
   291
      friend class FullUGraphBase;
deba@2116
   292
deba@2116
   293
    protected:
deba@2116
   294
      int id;
deba@2116
   295
      Node(int _id) { id = _id;}
deba@2116
   296
    public:
deba@2116
   297
      Node() {}
deba@2116
   298
      Node (Invalid) { id = -1; }
deba@2116
   299
      bool operator==(const Node node) const {return id == node.id;}
deba@2116
   300
      bool operator!=(const Node node) const {return id != node.id;}
deba@2116
   301
      bool operator<(const Node node) const {return id < node.id;}
deba@2116
   302
    };
deba@2116
   303
    
deba@2116
   304
deba@2116
   305
deba@2116
   306
    class Edge {
deba@2116
   307
      friend class FullUGraphBase;
deba@2116
   308
      
deba@2116
   309
    protected:
deba@2116
   310
      int id;  // _nodeNum * target + source;
deba@2116
   311
deba@2116
   312
      Edge(int _id) : id(_id) {}
deba@2116
   313
deba@2116
   314
    public:
deba@2116
   315
      Edge() { }
deba@2116
   316
      Edge (Invalid) { id = -1; }
deba@2116
   317
      bool operator==(const Edge edge) const {return id == edge.id;}
deba@2116
   318
      bool operator!=(const Edge edge) const {return id != edge.id;}
deba@2116
   319
      bool operator<(const Edge edge) const {return id < edge.id;}
deba@2116
   320
    };
deba@2116
   321
deba@2116
   322
    void first(Node& node) const {
deba@2116
   323
      node.id = _nodeNum - 1;
deba@2116
   324
    }
deba@2116
   325
deba@2116
   326
    static void next(Node& node) {
deba@2116
   327
      --node.id;
deba@2116
   328
    }
deba@2116
   329
deba@2116
   330
    void first(Edge& edge) const {
deba@2116
   331
      edge.id = _edgeNum - 1;
deba@2116
   332
    }
deba@2116
   333
deba@2116
   334
    static void next(Edge& edge) {
deba@2116
   335
      --edge.id;
deba@2116
   336
    }
deba@2116
   337
deba@2116
   338
    void firstOut(Edge& edge, const Node& node) const {      
deba@2116
   339
      int src = node.id;
deba@2116
   340
      int trg = 0;
deba@2116
   341
      edge.id = (trg < src ? src * (src - 1) / 2 + trg : -1);
deba@2116
   342
    }
deba@2116
   343
deba@2116
   344
    /// \todo with specialized iterators we can make faster iterating
deba@2116
   345
    void nextOut(Edge& edge) const {
deba@2116
   346
      int src = source(edge).id;
deba@2116
   347
      int trg = target(edge).id;
deba@2116
   348
      ++trg;
deba@2116
   349
      edge.id = (trg < src ? src * (src - 1) / 2 + trg : -1);
deba@2116
   350
    }
deba@2116
   351
deba@2116
   352
    void firstIn(Edge& edge, const Node& node) const {
deba@2116
   353
      int src = node.id + 1;
deba@2116
   354
      int trg = node.id;
deba@2116
   355
      edge.id = (src < _nodeNum ? src * (src - 1) / 2 + trg : -1);
deba@2116
   356
    }
deba@2116
   357
    
deba@2116
   358
    void nextIn(Edge& edge) const {
deba@2116
   359
      int src = source(edge).id;
deba@2116
   360
      int trg = target(edge).id;
deba@2116
   361
      ++src;
deba@2116
   362
      edge.id = (src < _nodeNum ? src * (src - 1) / 2 + trg : -1);
deba@2116
   363
    }
deba@2116
   364
deba@2116
   365
  };
deba@2116
   366
deba@2116
   367
  typedef UGraphExtender<UndirGraphExtender<FullUGraphBase> > 
deba@2116
   368
  ExtendedFullUGraphBase;
deba@2116
   369
deba@2116
   370
  /// \ingroup graphs
deba@2116
   371
  ///
deba@2116
   372
  /// \brief An undirected full graph class.
deba@2116
   373
  ///
deba@2116
   374
  /// This is a simple and fast undirected full graph implementation.
deba@2116
   375
  /// It is completely static, so you can neither add nor delete either
deba@2116
   376
  /// edges or nodes.
deba@2116
   377
  ///
deba@2116
   378
  /// The main difference beetween the \e FullGraph and \e FullUGraph class
deba@2116
   379
  /// is that this class conforms to the undirected graph concept and
deba@2116
   380
  /// it does not contain the loop edges.
deba@2116
   381
  ///
deba@2116
   382
  /// \sa FullGraph
deba@2116
   383
  ///
deba@2116
   384
  /// \author Balazs Dezso
deba@2116
   385
  class FullUGraph : public ExtendedFullUGraphBase {
deba@2116
   386
  public:
deba@2116
   387
deba@2116
   388
    typedef ExtendedFullUGraphBase Parent;
deba@2116
   389
deba@2116
   390
    /// \brief Constructor
deba@2116
   391
    FullUGraph() { construct(0); }
deba@2116
   392
deba@2116
   393
    /// \brief Constructor
deba@2116
   394
    FullUGraph(int n) { construct(n); }
deba@2116
   395
deba@2116
   396
    /// \brief Resize the graph
deba@2116
   397
    ///
deba@2116
   398
    /// Resize the graph. The function will fully destroy and build the graph.
deba@2116
   399
    /// This cause that the maps of the graph will reallocated
deba@2116
   400
    /// automatically and the previous values will be lost.
deba@2116
   401
    void resize(int n) {
deba@2116
   402
      Parent::getNotifier(Edge()).clear();
deba@2116
   403
      Parent::getNotifier(UEdge()).clear();
deba@2116
   404
      Parent::getNotifier(Node()).clear();
deba@2116
   405
      construct(n);
deba@2116
   406
      Parent::getNotifier(Node()).build();
deba@2116
   407
      Parent::getNotifier(UEdge()).build();
deba@2116
   408
      Parent::getNotifier(Edge()).build();
deba@2116
   409
    }
deba@2223
   410
deba@2223
   411
    /// \brief Returns the node with the given index.
deba@2223
   412
    ///
deba@2223
   413
    /// Returns the node with the given index. Because it is a
deba@2223
   414
    /// static size graph the node's of the graph can be indiced
deba@2223
   415
    /// by the range from 0 to \e nodeNum()-1 and the index of
deba@2223
   416
    /// the node can accessed by the \e index() member.
deba@2223
   417
    Node operator()(int index) const { return Parent::operator()(index); }
deba@2223
   418
deba@2223
   419
    /// \brief Returns the index of the node.
deba@2223
   420
    ///
deba@2223
   421
    /// Returns the index of the node. Because it is a
deba@2223
   422
    /// static size graph the node's of the graph can be indiced
deba@2223
   423
    /// by the range from 0 to \e nodeNum()-1 and the index of
deba@2223
   424
    /// the node can accessed by the \e index() member.
deba@2223
   425
    int index(const Node& node) const { return Parent::index(node); }
deba@2223
   426
deba@2223
   427
    /// \brief Number of nodes.
deba@2223
   428
    int nodeNum() const { return Parent::nodeNum(); }
deba@2223
   429
    /// \brief Number of edges.
deba@2223
   430
    int edgeNum() const { return Parent::edgeNum(); }
deba@2223
   431
    /// \brief Number of undirected edges.
deba@2223
   432
    int uEdgeNum() const { return Parent::uEdgeNum(); }
deba@2223
   433
deba@2223
   434
    /// \brief Returns the edge connects the given nodes.
deba@2223
   435
    ///
deba@2223
   436
    /// Returns the edge connects the given nodes.
deba@2223
   437
    Edge edge(const Node& u, const Node& v) const { 
deba@2223
   438
      if (Parent::index(u) > Parent::index(v)) {
deba@2223
   439
        return Parent::direct(Parent::edge(u, v), true);
deba@2223
   440
      } else if (Parent::index(u) == Parent::index(v)) {
deba@2223
   441
        return INVALID;
deba@2223
   442
      } else {
deba@2223
   443
        return Parent::direct(Parent::edge(v, u), false); 
deba@2223
   444
      }
deba@2223
   445
    }
deba@2223
   446
deba@2223
   447
    /// \brief Returns the undirected edge connects the given nodes.
deba@2223
   448
    ///
deba@2223
   449
    /// Returns the undirected edge connects the given nodes.
deba@2223
   450
    UEdge uEdge(const Node& u, const Node& v) const {
deba@2223
   451
      if (Parent::index(u) > Parent::index(v)) {
deba@2223
   452
        return Parent::edge(u, v);
deba@2223
   453
      } else if (Parent::index(u) == Parent::index(v)) {
deba@2223
   454
        return INVALID;
deba@2223
   455
      } else {
deba@2223
   456
        return Parent::edge(v, u);
deba@2223
   457
      }
deba@2223
   458
    }
deba@2116
   459
  };
deba@2116
   460
deba@2116
   461
deba@2116
   462
  class FullBpUGraphBase {
deba@2116
   463
  protected:
deba@2116
   464
deba@2116
   465
    int _aNodeNum;
deba@2116
   466
    int _bNodeNum;
deba@2116
   467
deba@2116
   468
    int _edgeNum;
deba@2116
   469
deba@2223
   470
  protected:
deba@2223
   471
deba@2223
   472
    FullBpUGraphBase() {}
deba@2223
   473
deba@2223
   474
    void construct(int aNodeNum, int bNodeNum) {
deba@2223
   475
      _aNodeNum = aNodeNum;
deba@2223
   476
      _bNodeNum = bNodeNum;
deba@2223
   477
      _edgeNum = aNodeNum * bNodeNum;
deba@2223
   478
    }
deba@2223
   479
deba@2116
   480
  public:
deba@2116
   481
deba@2116
   482
    class NodeSetError : public LogicError {
deba@2162
   483
    public:
alpar@2151
   484
      virtual const char* what() const throw() { 
deba@2116
   485
	return "lemon::FullBpUGraph::NodeSetError";
deba@2116
   486
      }
deba@2116
   487
    };
deba@2116
   488
  
deba@2116
   489
    class Node {
deba@2116
   490
      friend class FullBpUGraphBase;
deba@2116
   491
    protected:
deba@2116
   492
      int id;
deba@2116
   493
deba@2116
   494
      Node(int _id) : id(_id) {}
deba@2116
   495
    public:
deba@2116
   496
      Node() {}
deba@2116
   497
      Node(Invalid) { id = -1; }
deba@2116
   498
      bool operator==(const Node i) const {return id==i.id;}
deba@2116
   499
      bool operator!=(const Node i) const {return id!=i.id;}
deba@2116
   500
      bool operator<(const Node i) const {return id<i.id;}
deba@2116
   501
    };
deba@2116
   502
deba@2116
   503
    class UEdge {
deba@2116
   504
      friend class FullBpUGraphBase;
deba@2116
   505
    protected:
deba@2116
   506
      int id;
deba@2116
   507
deba@2116
   508
      UEdge(int _id) { id = _id;}
deba@2116
   509
    public:
deba@2116
   510
      UEdge() {}
deba@2116
   511
      UEdge (Invalid) { id = -1; }
deba@2116
   512
      bool operator==(const UEdge i) const {return id==i.id;}
deba@2116
   513
      bool operator!=(const UEdge i) const {return id!=i.id;}
deba@2116
   514
      bool operator<(const UEdge i) const {return id<i.id;}
deba@2116
   515
    };
deba@2116
   516
deba@2223
   517
    Node aNode(int index) const { return Node(index << 1); }
deba@2223
   518
    Node bNode(int index) const { return Node((index << 1) + 1); }
deba@2223
   519
deba@2223
   520
    int aNodeIndex(const Node& node) const { return node.id >> 1; }
deba@2223
   521
    int bNodeIndex(const Node& node) const { return node.id >> 1; }
deba@2223
   522
deba@2223
   523
    UEdge uEdge(const Node& u, const Node& v) const { 
deba@2223
   524
      if (((u.id ^ v.id) & 1) != 1) {
deba@2223
   525
        return UEdge(-1);
deba@2223
   526
      } else if ((u.id & 1) == 0) {
deba@2223
   527
        return UEdge((u.id >> 1) * _bNodeNum + (v.id >> 1));
deba@2223
   528
      } else {
deba@2223
   529
        return UEdge((v.id >> 1) * _bNodeNum + (u.id >> 1));
deba@2223
   530
      }
deba@2116
   531
    }
deba@2116
   532
deba@2116
   533
    void firstANode(Node& node) const {
deba@2116
   534
      node.id = 2 * _aNodeNum - 2;
deba@2116
   535
      if (node.id < 0) node.id = -1; 
deba@2116
   536
    }
deba@2116
   537
    void nextANode(Node& node) const {
deba@2116
   538
      node.id -= 2;
deba@2116
   539
      if (node.id < 0) node.id = -1; 
deba@2116
   540
    }
deba@2116
   541
deba@2116
   542
    void firstBNode(Node& node) const {
deba@2116
   543
      node.id = 2 * _bNodeNum - 1;
deba@2116
   544
    }
deba@2116
   545
    void nextBNode(Node& node) const {
deba@2116
   546
      node.id -= 2;
deba@2116
   547
    }
deba@2116
   548
deba@2116
   549
    void first(Node& node) const {
deba@2116
   550
      if (_aNodeNum > 0) {
deba@2116
   551
	node.id = 2 * _aNodeNum - 2;
deba@2116
   552
      } else {
deba@2116
   553
	node.id = 2 * _bNodeNum - 1;
deba@2116
   554
      }
deba@2116
   555
    }
deba@2116
   556
    void next(Node& node) const {
deba@2116
   557
      node.id -= 2;
deba@2116
   558
      if (node.id == -2) {
deba@2116
   559
	node.id = 2 * _bNodeNum - 1;
deba@2116
   560
      }
deba@2116
   561
    }
deba@2116
   562
  
deba@2116
   563
    void first(UEdge& edge) const {
deba@2116
   564
      edge.id = _edgeNum - 1;
deba@2116
   565
    }
deba@2116
   566
    void next(UEdge& edge) const {
deba@2116
   567
      --edge.id;
deba@2116
   568
    }
deba@2116
   569
deba@2116
   570
    void firstFromANode(UEdge& edge, const Node& node) const {
deba@2116
   571
      LEMON_ASSERT((node.id & 1) == 0, NodeSetError());
deba@2116
   572
      edge.id = (node.id >> 1) * _bNodeNum;
deba@2116
   573
    }
deba@2116
   574
    void nextFromANode(UEdge& edge) const {
deba@2116
   575
      ++(edge.id);
deba@2116
   576
      if (edge.id % _bNodeNum == 0) edge.id = -1;
deba@2116
   577
    }
deba@2116
   578
deba@2116
   579
    void firstFromBNode(UEdge& edge, const Node& node) const {
deba@2116
   580
      LEMON_ASSERT((node.id & 1) == 1, NodeSetError());
deba@2116
   581
      edge.id = (node.id >> 1);
deba@2116
   582
    }
deba@2116
   583
    void nextFromBNode(UEdge& edge) const {
deba@2116
   584
      edge.id += _bNodeNum;
deba@2116
   585
      if (edge.id >= _edgeNum) edge.id = -1;
deba@2116
   586
    }
deba@2116
   587
deba@2116
   588
    static int id(const Node& node) {
deba@2116
   589
      return node.id;
deba@2116
   590
    }
deba@2116
   591
    static Node nodeFromId(int id) {
deba@2116
   592
      return Node(id);
deba@2116
   593
    }
deba@2116
   594
    int maxNodeId() const {
deba@2116
   595
      return _aNodeNum > _bNodeNum ? 
deba@2116
   596
	_aNodeNum * 2 - 2 : _bNodeNum * 2 - 1;
deba@2116
   597
    }
deba@2116
   598
  
deba@2116
   599
    static int id(const UEdge& edge) {
deba@2116
   600
      return edge.id;
deba@2116
   601
    }
deba@2116
   602
    static UEdge uEdgeFromId(int id) {
deba@2116
   603
      return UEdge(id);
deba@2116
   604
    }
deba@2116
   605
    int maxUEdgeId() const {
deba@2116
   606
      return _edgeNum - 1;
deba@2116
   607
    }
deba@2116
   608
  
deba@2116
   609
    static int aNodeId(const Node& node) {
deba@2116
   610
      return node.id >> 1;
deba@2116
   611
    }
deba@2231
   612
    static Node nodeFromANodeId(int id) {
deba@2116
   613
      return Node(id << 1);
deba@2116
   614
    }
deba@2116
   615
    int maxANodeId() const {
deba@2116
   616
      return _aNodeNum;
deba@2116
   617
    }
deba@2116
   618
deba@2116
   619
    static int bNodeId(const Node& node) {
deba@2116
   620
      return node.id >> 1;
deba@2116
   621
    }
deba@2231
   622
    static Node nodeFromBNodeId(int id) {
deba@2116
   623
      return Node((id << 1) + 1);
deba@2116
   624
    }
deba@2116
   625
    int maxBNodeId() const {
deba@2116
   626
      return _bNodeNum;
deba@2116
   627
    }
deba@2116
   628
deba@2116
   629
    Node aNode(const UEdge& edge) const {
deba@2116
   630
      return Node((edge.id / _bNodeNum) << 1);
deba@2116
   631
    }
deba@2116
   632
    Node bNode(const UEdge& edge) const {
deba@2116
   633
      return Node(((edge.id % _bNodeNum) << 1) + 1);
deba@2116
   634
    }
deba@2116
   635
deba@2116
   636
    static bool aNode(const Node& node) {
deba@2116
   637
      return (node.id & 1) == 0;
deba@2116
   638
    }
deba@2116
   639
deba@2116
   640
    static bool bNode(const Node& node) {
deba@2116
   641
      return (node.id & 1) == 1;
deba@2116
   642
    }
deba@2116
   643
deba@2116
   644
deba@2116
   645
    typedef True NodeNumTag;
deba@2116
   646
    int nodeNum() const { return _aNodeNum + _bNodeNum; }
deba@2116
   647
    int aNodeNum() const { return _aNodeNum; }
deba@2116
   648
    int bNodeNum() const { return _bNodeNum; }
deba@2116
   649
deba@2116
   650
    typedef True EdgeNumTag;
deba@2116
   651
    int uEdgeNum() const { return _edgeNum; }
deba@2116
   652
deba@2223
   653
deba@2223
   654
    typedef True FindEdgeTag;
deba@2223
   655
    UEdge findUEdge(Node u, Node v, UEdge prev = INVALID) const {
deba@2223
   656
      if (prev.id != -1 || ((u.id ^ v.id) & 1) != 1) {
deba@2223
   657
        return UEdge(-1);
deba@2223
   658
      } else if ((u.id & 1) == 0) {
deba@2223
   659
        return UEdge((u.id >> 1) * _bNodeNum + (v.id >> 1));
deba@2223
   660
      } else {
deba@2223
   661
        return UEdge((v.id >> 1) * _bNodeNum + (u.id >> 1));
deba@2223
   662
      }
deba@2223
   663
    }
deba@2223
   664
deba@2116
   665
  };
deba@2116
   666
deba@2116
   667
deba@2231
   668
  typedef BpUGraphExtender<BidirBpUGraphExtender<FullBpUGraphBase> > 
deba@2231
   669
  ExtendedFullBpUGraphBase;
deba@2116
   670
deba@2116
   671
deba@2116
   672
  /// \ingroup graphs
deba@2116
   673
  ///
deba@2116
   674
  /// \brief An undirected full bipartite graph class.
deba@2116
   675
  ///
deba@2116
   676
  /// This is a simple and fast bipartite undirected full graph implementation.
deba@2116
   677
  /// It is completely static, so you can neither add nor delete either
deba@2116
   678
  /// edges or nodes.
deba@2116
   679
  ///
deba@2116
   680
  /// \author Balazs Dezso
deba@2116
   681
  class FullBpUGraph : 
deba@2116
   682
    public ExtendedFullBpUGraphBase {
deba@2116
   683
  public:
deba@2116
   684
deba@2116
   685
    typedef ExtendedFullBpUGraphBase Parent;
deba@2116
   686
deba@2116
   687
    FullBpUGraph() {
deba@2116
   688
      Parent::construct(0, 0);
deba@2116
   689
    }
deba@2116
   690
deba@2116
   691
    FullBpUGraph(int aNodeNum, int bNodeNum) {
deba@2116
   692
      Parent::construct(aNodeNum, bNodeNum);
deba@2116
   693
    }
deba@2116
   694
deba@2116
   695
    /// \brief Resize the graph
deba@2116
   696
    ///
deba@2223
   697
    /// Resize the graph
deba@2116
   698
    void resize(int n, int m) {
deba@2116
   699
      Parent::getNotifier(Edge()).clear();
deba@2116
   700
      Parent::getNotifier(UEdge()).clear();
deba@2116
   701
      Parent::getNotifier(Node()).clear();
deba@2116
   702
      Parent::getNotifier(ANode()).clear();
deba@2116
   703
      Parent::getNotifier(BNode()).clear();
deba@2116
   704
      construct(n, m);
deba@2116
   705
      Parent::getNotifier(ANode()).build();
deba@2116
   706
      Parent::getNotifier(BNode()).build();
deba@2116
   707
      Parent::getNotifier(Node()).build();
deba@2116
   708
      Parent::getNotifier(UEdge()).build();
deba@2116
   709
      Parent::getNotifier(Edge()).build();
deba@2116
   710
    }
deba@2223
   711
deba@2223
   712
    /// \brief Number of nodes.
deba@2223
   713
    int nodeNum() const { return Parent::nodeNum(); }
deba@2223
   714
    /// \brief Number of A-nodes.
deba@2223
   715
    int aNodeNum() const { return Parent::aNodeNum(); }
deba@2223
   716
    /// \brief Number of B-nodes.
deba@2223
   717
    int bNodeNum() const { return Parent::bNodeNum(); }
deba@2223
   718
    /// \brief Number of edges.
deba@2223
   719
    int edgeNum() const { return Parent::edgeNum(); }
deba@2223
   720
    /// \brief Number of undirected edges.
deba@2223
   721
    int uEdgeNum() const { return Parent::uEdgeNum(); }
deba@2223
   722
deba@2223
   723
deba@2223
   724
    using Parent::aNode;
deba@2223
   725
    using Parent::bNode;
deba@2223
   726
deba@2223
   727
    /// \brief Returns the A-node with the given index.
deba@2223
   728
    ///
deba@2223
   729
    /// Returns the A-node with the given index. Because it is a
deba@2223
   730
    /// static size graph the node's of the graph can be indiced
deba@2223
   731
    /// by the range from 0 to \e aNodeNum()-1 and the index of
deba@2223
   732
    /// the node can accessed by the \e aNodeIndex() member.
deba@2223
   733
    Node aNode(int index) const { return Parent::aNode(index); }
deba@2223
   734
deba@2223
   735
    /// \brief Returns the B-node with the given index.
deba@2223
   736
    ///
deba@2223
   737
    /// Returns the B-node with the given index. Because it is a
deba@2223
   738
    /// static size graph the node's of the graph can be indiced
deba@2223
   739
    /// by the range from 0 to \e bNodeNum()-1 and the index of
deba@2223
   740
    /// the node can accessed by the \e bNodeIndex() member.
deba@2223
   741
    Node bNode(int index) const { return Parent::bNode(index); }
deba@2223
   742
deba@2223
   743
    /// \brief Returns the index of the A-node.
deba@2223
   744
    ///
deba@2223
   745
    /// Returns the index of the A-node. Because it is a
deba@2223
   746
    /// static size graph the node's of the graph can be indiced
deba@2223
   747
    /// by the range from 0 to \e aNodeNum()-1 and the index of
deba@2223
   748
    /// the node can accessed by the \e aNodeIndex() member.
deba@2223
   749
    int aNodeIndex(const Node& node) const { return Parent::aNodeIndex(node); }
deba@2223
   750
deba@2223
   751
    /// \brief Returns the index of the B-node.
deba@2223
   752
    ///
deba@2223
   753
    /// Returns the index of the B-node. Because it is a
deba@2223
   754
    /// static size graph the node's of the graph can be indiced
deba@2223
   755
    /// by the range from 0 to \e bNodeNum()-1 and the index of
deba@2223
   756
    /// the node can accessed by the \e bNodeIndex() member.
deba@2223
   757
    int bNodeIndex(const Node& node) const { return Parent::bNodeIndex(node); }
deba@2223
   758
deba@2223
   759
    /// \brief Returns the edge connects the given nodes.
deba@2223
   760
    ///
deba@2223
   761
    /// Returns the edge connects the given nodes.
deba@2223
   762
    Edge edge(const Node& u, const Node& v) const {
deba@2223
   763
      UEdge uedge = Parent::uEdge(u, v);
deba@2223
   764
      if (uedge != INVALID) {
deba@2223
   765
        return Parent::direct(uedge, Parent::aNode(u));
deba@2223
   766
      } else {
deba@2223
   767
        return INVALID;
deba@2223
   768
      }
deba@2223
   769
    }
deba@2223
   770
deba@2223
   771
    /// \brief Returns the undirected edge connects the given nodes.
deba@2223
   772
    ///
deba@2223
   773
    /// Returns the undirected edge connects the given nodes.
deba@2223
   774
    UEdge uEdge(const Node& u, const Node& v) const {
deba@2223
   775
      return Parent::uEdge(u, v);
deba@2223
   776
    }
deba@2116
   777
  };
deba@2116
   778
alpar@921
   779
} //namespace lemon
alpar@591
   780
alpar@591
   781
alpar@921
   782
#endif //LEMON_FULL_GRAPH_H