lemon/static_graph.h
author alpar
Tue, 13 Mar 2007 12:33:40 +0000
changeset 2406 0ffc78641b34
parent 2329 3f4a04a9b7bf
child 2553 bfced05fa852
permissions -rw-r--r--
Better doc.
deba@2293
     1
/* -*- C++ -*-
deba@2293
     2
 *
deba@2293
     3
 * This file is a part of LEMON, a generic C++ optimization library
deba@2293
     4
 *
alpar@2391
     5
 * Copyright (C) 2003-2007
deba@2293
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@2293
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@2293
     8
 *
deba@2293
     9
 * Permission to use, modify and distribute this software is granted
deba@2293
    10
 * provided that this copyright notice appears in all copies. For
deba@2293
    11
 * precise terms see the accompanying LICENSE file.
deba@2293
    12
 *
deba@2293
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@2293
    14
 * express or implied, and with no claim as to its suitability for any
deba@2293
    15
 * purpose.
deba@2293
    16
 *
deba@2293
    17
 */
deba@2293
    18
deba@2293
    19
#ifndef LEMON_STATIC_GRAPH_H
deba@2293
    20
#define LEMON_STATIC_GRAPH_H
deba@2293
    21
deba@2293
    22
#include <lemon/bits/graph_extender.h>
deba@2293
    23
#include <lemon/graph_utils.h>
deba@2293
    24
deba@2293
    25
namespace lemon {
deba@2293
    26
deba@2293
    27
  class StaticGraphBase {
deba@2293
    28
  public:
deba@2293
    29
deba@2293
    30
    StaticGraphBase() 
deba@2293
    31
      : node_num(-1), edge_num(0), 
deba@2293
    32
        node_first_out(0), node_first_in(0),
deba@2293
    33
        edge_source(0), edge_target(0), 
deba@2293
    34
        edge_next_in(0), edge_next_out(0) {}
deba@2293
    35
    
deba@2293
    36
    ~StaticGraphBase() {
deba@2293
    37
      if (node_num != -1) {
deba@2293
    38
        delete[] node_first_out;
deba@2293
    39
        delete[] node_first_in;
deba@2293
    40
        delete[] edge_source;
deba@2293
    41
        delete[] edge_target;
deba@2293
    42
        delete[] edge_next_out;
deba@2293
    43
        delete[] edge_next_in;
deba@2293
    44
      }
deba@2293
    45
    }
deba@2293
    46
deba@2293
    47
    class Node {
deba@2293
    48
      friend class StaticGraphBase;
deba@2293
    49
    protected:
deba@2293
    50
      int id;
deba@2293
    51
      Node(int _id) : id(_id) {}
deba@2293
    52
    public:
deba@2293
    53
      Node() {}
deba@2293
    54
      Node (Invalid) : id(-1) {}
deba@2293
    55
      bool operator==(const Node& node) const {return id == node.id;}
deba@2293
    56
      bool operator!=(const Node& node) const {return id != node.id;}
deba@2293
    57
      bool operator<(const Node& node) const {return id < node.id;}
deba@2293
    58
    };
deba@2293
    59
deba@2293
    60
    class Edge {
deba@2293
    61
      friend class StaticGraphBase;      
deba@2293
    62
    protected:
deba@2293
    63
      int id;
deba@2293
    64
      Edge(int _id) : id(_id) {}
deba@2293
    65
    public:
deba@2293
    66
      Edge() { }
deba@2293
    67
      Edge (Invalid) { id = -1; }
deba@2293
    68
      bool operator==(const Edge& edge) const {return id == edge.id;}
deba@2293
    69
      bool operator!=(const Edge& edge) const {return id != edge.id;}
deba@2293
    70
      bool operator<(const Edge& edge) const {return id < edge.id;}
deba@2293
    71
    };
deba@2293
    72
deba@2293
    73
    Node source(const Edge& e) const { return Node(edge_source[e.id]); }
deba@2293
    74
    Node target(const Edge& e) const { return Node(edge_target[e.id]); }
deba@2293
    75
deba@2293
    76
    void first(Node& n) const { n.id = node_num - 1; }
deba@2293
    77
    void next(Node& n) const { --n.id; }
deba@2293
    78
deba@2293
    79
    void first(Edge& n) const { n.id = edge_num - 1; }
deba@2293
    80
    void next(Edge& n) const { --n.id; }
deba@2293
    81
deba@2293
    82
    void firstOut(Edge& e, const Node& n) const { 
deba@2293
    83
      e.id = node_first_out[n.id] != node_first_out[n.id + 1] ? 
deba@2293
    84
        node_first_out[n.id] : -1;
deba@2293
    85
    }
deba@2293
    86
    void nextOut(Edge& e) const { e.id = edge_next_out[e.id]; }
deba@2293
    87
deba@2293
    88
    void firstIn(Edge& e, const Node& n) const { e.id = node_first_in[n.id]; }
deba@2293
    89
    void nextIn(Edge& e) const { e.id = edge_next_in[e.id]; }
deba@2293
    90
    
deba@2293
    91
deba@2293
    92
    int id(const Node& n) const { return n.id; }
deba@2293
    93
    Node nodeFromId(int id) const { return Node(id); }
deba@2293
    94
    int maxNodeId() const { return node_num - 1; }
deba@2293
    95
deba@2293
    96
    int id(const Edge& e) const { return e.id; }
deba@2293
    97
    Edge edgeFromId(int id) const { return Edge(id); }
deba@2293
    98
    int maxEdgeId() const { return edge_num - 1; }
deba@2293
    99
deba@2293
   100
    typedef True NodeNumTag;
deba@2293
   101
    int nodeNum() const { return node_num; }
deba@2293
   102
    typedef True EdgeNumTag;
deba@2293
   103
    int edgeNum() const { return edge_num; }
deba@2293
   104
deba@2293
   105
  private:
deba@2293
   106
deba@2293
   107
    template <typename Graph, typename NodeRefMap>
deba@2293
   108
    class EdgeLess {
deba@2293
   109
    public:
deba@2293
   110
      typedef typename Graph::Edge Edge;
deba@2293
   111
deba@2293
   112
      EdgeLess(const Graph &_graph, const NodeRefMap& _nodeRef) 
deba@2293
   113
        : graph(_graph), nodeRef(_nodeRef) {}
deba@2293
   114
      
deba@2293
   115
      bool operator()(const Edge& left, const Edge& right) const {
deba@2293
   116
	return nodeRef[graph.target(left)] < nodeRef[graph.target(right)];
deba@2293
   117
      }
deba@2293
   118
    private:
deba@2293
   119
      const Graph& graph;
deba@2293
   120
      const NodeRefMap& nodeRef;
deba@2293
   121
    };
deba@2293
   122
    
deba@2293
   123
  public:
deba@2293
   124
deba@2329
   125
    typedef True BuildTag;
deba@2293
   126
    
deba@2293
   127
    template <typename Graph, typename NodeRefMap, typename EdgeRefMap>
deba@2329
   128
    void build(const Graph& graph, NodeRefMap& nodeRef, EdgeRefMap& edgeRef) {
deba@2293
   129
deba@2293
   130
      if (node_num != -1) {
deba@2293
   131
        delete[] node_first_out;
deba@2293
   132
        delete[] node_first_in;
deba@2293
   133
        delete[] edge_source;
deba@2293
   134
        delete[] edge_target;
deba@2293
   135
        delete[] edge_next_out;
deba@2293
   136
        delete[] edge_next_in;
deba@2293
   137
      }
deba@2293
   138
deba@2293
   139
      typedef typename Graph::Node GNode;
deba@2293
   140
      typedef typename Graph::Edge GEdge;
deba@2293
   141
deba@2293
   142
      node_num = countNodes(graph);
deba@2293
   143
      edge_num = countEdges(graph);
deba@2293
   144
deba@2293
   145
      node_first_out = new int[node_num + 1];
deba@2293
   146
      node_first_in = new int[node_num];
deba@2293
   147
deba@2293
   148
      edge_source = new int[edge_num];
deba@2293
   149
      edge_target = new int[edge_num];
deba@2293
   150
      edge_next_out = new int[edge_num];
deba@2293
   151
      edge_next_in = new int[edge_num];
deba@2293
   152
deba@2293
   153
      int node_index = 0;
deba@2293
   154
      for (typename Graph::NodeIt n(graph); n != INVALID; ++n) {
deba@2293
   155
        nodeRef[n] = Node(node_index);
deba@2293
   156
        node_first_in[node_index] = -1;
deba@2293
   157
        ++node_index;
deba@2293
   158
      }
deba@2293
   159
deba@2293
   160
      EdgeLess<Graph, NodeRefMap> edgeLess(graph, nodeRef);
deba@2293
   161
deba@2293
   162
      int edge_index = 0;
deba@2293
   163
      for (typename Graph::NodeIt n(graph); n != INVALID; ++n) {
deba@2293
   164
        int source = nodeRef[n].id;
deba@2293
   165
        std::vector<GEdge> edges;
deba@2293
   166
        for (typename Graph::OutEdgeIt e(graph, n); e != INVALID; ++e) {
deba@2293
   167
          edges.push_back(e);
deba@2293
   168
        }
deba@2293
   169
        if (!edges.empty()) {
deba@2293
   170
          node_first_out[source] = edge_index;
deba@2293
   171
          std::sort(edges.begin(), edges.end(), edgeLess);
deba@2293
   172
          for (typename std::vector<GEdge>::iterator it = edges.begin();
deba@2293
   173
               it != edges.end(); ++it) {
deba@2293
   174
            int target = nodeRef[graph.target(*it)].id;
deba@2293
   175
            edgeRef[*it] = Edge(edge_index);
deba@2293
   176
            edge_source[edge_index] = source; 
deba@2293
   177
            edge_target[edge_index] = target;
deba@2293
   178
            edge_next_in[edge_index] = node_first_in[target];
deba@2293
   179
            node_first_in[target] = edge_index;
deba@2293
   180
            edge_next_out[edge_index] = edge_index + 1;
deba@2293
   181
            ++edge_index;
deba@2293
   182
          }
deba@2293
   183
          edge_next_out[edge_index - 1] = -1;
deba@2293
   184
        } else {
deba@2293
   185
          node_first_out[source] = edge_index;
deba@2293
   186
        }
deba@2293
   187
      }
deba@2293
   188
      node_first_out[node_num] = edge_num;
deba@2293
   189
    }
deba@2293
   190
deba@2293
   191
  protected:
deba@2293
   192
deba@2293
   193
    void fastFirstOut(Edge& e, const Node& n) const {
deba@2293
   194
      e.id = node_first_out[n.id];
deba@2293
   195
    }
deba@2293
   196
deba@2293
   197
    static void fastNextOut(Edge& e) {
deba@2293
   198
      ++e.id;
deba@2293
   199
    }
deba@2293
   200
    void fastLastOut(Edge& e, const Node& n) const {
deba@2293
   201
      e.id = node_first_out[n.id + 1];
deba@2293
   202
    }
deba@2293
   203
    
deba@2293
   204
  private:
deba@2293
   205
    int node_num;
deba@2293
   206
    int edge_num;
deba@2293
   207
    int *node_first_out;
deba@2293
   208
    int *node_first_in;
deba@2293
   209
    int *edge_source;
deba@2293
   210
    int *edge_target;
deba@2293
   211
    int *edge_next_in;
deba@2293
   212
    int *edge_next_out;
deba@2293
   213
  };
deba@2293
   214
deba@2293
   215
  typedef GraphExtender<StaticGraphBase> ExtendedStaticGraphBase;
deba@2293
   216
deba@2293
   217
deba@2293
   218
  class StaticGraph : public ExtendedStaticGraphBase {
deba@2293
   219
  public:
deba@2293
   220
deba@2293
   221
    typedef ExtendedStaticGraphBase Parent;
deba@2293
   222
deba@2293
   223
  protected:
deba@2293
   224
deba@2293
   225
    using Parent::fastFirstOut;
deba@2293
   226
    using Parent::fastNextOut;
deba@2293
   227
    using Parent::fastLastOut;
deba@2293
   228
    
deba@2293
   229
  public:
deba@2293
   230
    
deba@2293
   231
    class OutEdgeIt : public Edge {
deba@2293
   232
    public:
deba@2293
   233
deba@2293
   234
      OutEdgeIt() { }
deba@2293
   235
deba@2293
   236
      OutEdgeIt(Invalid i) : Edge(i) { }
deba@2293
   237
deba@2293
   238
      OutEdgeIt(const StaticGraph& graph, const Node& node) {
deba@2293
   239
	graph.fastFirstOut(*this, node);
deba@2293
   240
	graph.fastLastOut(last, node);
deba@2293
   241
        if (last == *this) *this = INVALID;
deba@2293
   242
      }
deba@2293
   243
deba@2293
   244
      OutEdgeIt(const StaticGraph& graph, const Edge& edge) : Edge(edge) {
deba@2293
   245
        graph.fastLastOut(last, graph.source(edge));
deba@2293
   246
      }
deba@2293
   247
deba@2293
   248
      OutEdgeIt& operator++() { 
deba@2293
   249
        StaticGraph::fastNextOut(*this);
deba@2293
   250
        if (last == *this) *this = INVALID;
deba@2293
   251
        return *this; 
deba@2293
   252
      }
deba@2293
   253
deba@2293
   254
    private:
deba@2293
   255
      Edge last;
deba@2293
   256
    };
deba@2293
   257
    
deba@2293
   258
  };
deba@2293
   259
deba@2293
   260
}
deba@2293
   261
deba@2293
   262
#endif