lemon/topology.h
author alpar
Mon, 24 Oct 2005 08:11:21 +0000
changeset 1735 41e96cd91d6d
parent 1698 755cdc461ddd
child 1739 b1385f5da81b
permissions -rw-r--r--
New version of XML reader/writer.
Now, there are only a single XmlIo class both for reading and writing.
deba@1698
     1
/* -*- C++ -*-
deba@1698
     2
 * lemon/topology.h - Part of LEMON, a generic C++ optimization library
deba@1698
     3
 *
deba@1698
     4
 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@1698
     5
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@1698
     6
 *
deba@1698
     7
 * Permission to use, modify and distribute this software is granted
deba@1698
     8
 * provided that this copyright notice appears in all copies. For
deba@1698
     9
 * precise terms see the accompanying LICENSE file.
deba@1698
    10
 *
deba@1698
    11
 * This software is provided "AS IS" with no warranty of any kind,
deba@1698
    12
 * express or implied, and with no claim as to its suitability for any
deba@1698
    13
 * purpose.
deba@1698
    14
 *
deba@1698
    15
 */
deba@1698
    16
deba@1698
    17
#ifndef LEMON_TOPOLOGY_H
deba@1698
    18
#define LEMON_TOPOLOGY_H
deba@1698
    19
deba@1698
    20
#include <lemon/dfs.h>
deba@1698
    21
#include <lemon/graph_utils.h>
deba@1698
    22
deba@1698
    23
#include <lemon/concept/graph.h>
deba@1698
    24
#include <lemon/concept/undir_graph.h>
deba@1698
    25
#include <lemon/concept_check.h>
deba@1698
    26
deba@1698
    27
/// \ingroup flowalgs
deba@1698
    28
/// \file
deba@1698
    29
/// \brief Topology related algorithms
deba@1698
    30
///
deba@1698
    31
/// Topology related algorithms
deba@1698
    32
deba@1698
    33
namespace lemon {
deba@1698
    34
deba@1698
    35
  namespace _topology_bits {
deba@1698
    36
    
deba@1698
    37
    template <typename NodeMap>
deba@1698
    38
    class BackCounterMap {
deba@1698
    39
    public:
deba@1698
    40
      BackCounterMap(NodeMap& _nodeMap, int _counter)
deba@1698
    41
	: nodeMap(_nodeMap), counter(_counter) {}
deba@1698
    42
deba@1698
    43
      void set(typename NodeMap::Key key, bool val) {
deba@1698
    44
	if (val) {
deba@1698
    45
	  nodeMap.set(key, --counter);
deba@1698
    46
	} else {
deba@1698
    47
	  nodeMap.set(key, -1);
deba@1698
    48
	}
deba@1698
    49
      }
deba@1698
    50
deba@1698
    51
      bool operator[](typename NodeMap::Key key) const {
deba@1698
    52
	return nodeMap[key] != -1;
deba@1698
    53
      }
deba@1698
    54
deba@1698
    55
    private:
deba@1698
    56
      NodeMap& nodeMap;
deba@1698
    57
      int counter;
deba@1698
    58
    };
deba@1698
    59
  }
deba@1698
    60
deba@1698
    61
  // \todo Its to special output // ReadWriteMap
deba@1698
    62
  template <typename Graph, typename NodeMap>
deba@1698
    63
  bool topological_sort(const Graph& graph, NodeMap& nodeMap) {
deba@1698
    64
    using namespace _topology_bits;
deba@1698
    65
deba@1698
    66
    checkConcept<concept::StaticGraph, Graph>();
deba@1698
    67
    checkConcept<concept::ReadWriteMap<typename Graph::Node, int>, NodeMap>();
deba@1698
    68
deba@1698
    69
    typedef typename Graph::Node Node;
deba@1698
    70
    typedef typename Graph::NodeIt NodeIt;
deba@1698
    71
    typedef typename Graph::Edge Edge;
deba@1698
    72
deba@1698
    73
    typedef BackCounterMap<NodeMap> ProcessedMap;
deba@1698
    74
deba@1698
    75
    typename Dfs<Graph>::template DefProcessedMap<ProcessedMap>::
deba@1709
    76
      Create dfs(graph);
deba@1698
    77
deba@1698
    78
    ProcessedMap processed(nodeMap, countNodes(graph));
deba@1698
    79
deba@1698
    80
    dfs.processedMap(processed);
deba@1698
    81
    dfs.init();
deba@1698
    82
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1698
    83
      if (!dfs.reached(it)) {
deba@1698
    84
	dfs.addSource(it);
deba@1698
    85
	while (!dfs.emptyQueue()) {
deba@1698
    86
	  Edge edge = dfs.nextEdge();
deba@1698
    87
	  Node target = graph.target(edge);
deba@1698
    88
	  if (dfs.reached(target) && !processed[target]) {
deba@1698
    89
	    return false;
deba@1698
    90
	  }
deba@1698
    91
	  dfs.processNextEdge();
deba@1698
    92
	}
deba@1698
    93
      }
deba@1698
    94
    }    
deba@1698
    95
    return true;
deba@1698
    96
  }
deba@1698
    97
deba@1698
    98
  /// \brief Check that the given graph is a DAG.
deba@1698
    99
  ///
deba@1698
   100
  /// Check that the given graph is a DAG. The DAG is
deba@1698
   101
  /// an Directed Acyclic Graph.
deba@1698
   102
  template <typename Graph>
deba@1698
   103
  bool dag(const Graph& graph) {
deba@1698
   104
deba@1698
   105
    checkConcept<concept::StaticGraph, Graph>();
deba@1698
   106
deba@1698
   107
    typedef typename Graph::Node Node;
deba@1698
   108
    typedef typename Graph::NodeIt NodeIt;
deba@1698
   109
    typedef typename Graph::Edge Edge;
deba@1698
   110
deba@1698
   111
    typedef typename Graph::template NodeMap<bool> ProcessedMap;
deba@1698
   112
deba@1698
   113
    typename Dfs<Graph>::template DefProcessedMap<ProcessedMap>::
deba@1709
   114
      Create dfs(graph);
deba@1698
   115
deba@1698
   116
    ProcessedMap processed(graph);
deba@1698
   117
    dfs.processedMap(processed);
deba@1698
   118
deba@1698
   119
    dfs.init();
deba@1698
   120
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1698
   121
      if (!dfs.reached(it)) {
deba@1698
   122
	dfs.addSource(it);
deba@1698
   123
	while (!dfs.emptyQueue()) {
deba@1698
   124
	  Edge edge = dfs.nextEdge();
deba@1698
   125
	  Node target = graph.target(edge);
deba@1698
   126
	  if (dfs.reached(target) && !processed[target]) {
deba@1698
   127
	    return false;
deba@1698
   128
	  }
deba@1698
   129
	  dfs.processNextEdge();
deba@1698
   130
	}
deba@1698
   131
      }
deba@1698
   132
    }    
deba@1698
   133
    return true;
deba@1698
   134
  }
deba@1698
   135
deba@1698
   136
  // UndirGraph algorithms
deba@1698
   137
deba@1698
   138
  /// \brief Check that the given undirected graph is connected.
deba@1698
   139
  ///
deba@1698
   140
  /// Check that the given undirected graph connected.
deba@1698
   141
  template <typename UndirGraph>
deba@1698
   142
  bool connected(const UndirGraph& graph) {
deba@1698
   143
    checkConcept<concept::UndirGraph, UndirGraph>();
deba@1698
   144
    typedef typename UndirGraph::NodeIt NodeIt;
deba@1698
   145
    if (NodeIt(graph) == INVALID) return false;
deba@1698
   146
    Dfs<UndirGraph> dfs(graph);
deba@1698
   147
    dfs.run(NodeIt(graph));
deba@1698
   148
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1698
   149
      if (!dfs.reached(it)) {
deba@1698
   150
	return false;
deba@1698
   151
      }
deba@1698
   152
    }
deba@1698
   153
    return true;
deba@1698
   154
  }
deba@1698
   155
deba@1698
   156
  /// \brief Check that the given undirected graph is acyclic.
deba@1698
   157
  ///
deba@1698
   158
  /// Check that the given undirected graph acyclic.
deba@1698
   159
  template <typename UndirGraph>
deba@1698
   160
  bool acyclic(const UndirGraph& graph) {
deba@1698
   161
    checkConcept<concept::UndirGraph, UndirGraph>();
deba@1698
   162
    typedef typename UndirGraph::Node Node;
deba@1698
   163
    typedef typename UndirGraph::NodeIt NodeIt;
deba@1698
   164
    typedef typename UndirGraph::Edge Edge;
deba@1698
   165
    Dfs<UndirGraph> dfs(graph);
deba@1698
   166
    dfs.init();
deba@1698
   167
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1698
   168
      if (!dfs.reached(it)) {
deba@1698
   169
	dfs.addSource(it);
deba@1698
   170
	while (!dfs.emptyQueue()) {
deba@1698
   171
	  Edge edge = dfs.nextEdge();
deba@1698
   172
	  Node source = graph.source(edge);
deba@1698
   173
	  Node target = graph.target(edge);
deba@1698
   174
	  if (dfs.reached(target) && 
deba@1698
   175
	      dfs.pred(source) != graph.oppositeEdge(edge)) {
deba@1698
   176
	    return false;
deba@1698
   177
	  }
deba@1698
   178
	  dfs.processNextEdge();
deba@1698
   179
	}
deba@1698
   180
      }
deba@1698
   181
    }
deba@1698
   182
    return true;
deba@1698
   183
  }
deba@1698
   184
deba@1698
   185
  /// \brief Check that the given undirected graph is tree.
deba@1698
   186
  ///
deba@1698
   187
  /// Check that the given undirected graph is tree.
deba@1698
   188
  template <typename UndirGraph>
deba@1698
   189
  bool tree(const UndirGraph& graph) {
deba@1698
   190
    checkConcept<concept::UndirGraph, UndirGraph>();
deba@1698
   191
    typedef typename UndirGraph::Node Node;
deba@1698
   192
    typedef typename UndirGraph::NodeIt NodeIt;
deba@1698
   193
    typedef typename UndirGraph::Edge Edge;
deba@1698
   194
    if (NodeIt(graph) == INVALID) return false;
deba@1698
   195
    Dfs<UndirGraph> dfs(graph);
deba@1698
   196
    dfs.init();
deba@1698
   197
    dfs.addSource(NodeIt(graph));
deba@1698
   198
    while (!dfs.emptyQueue()) {
deba@1698
   199
      Edge edge = dfs.nextEdge();
deba@1698
   200
      Node source = graph.source(edge);
deba@1698
   201
      Node target = graph.target(edge);
deba@1698
   202
      if (dfs.reached(target) && 
deba@1698
   203
	  dfs.pred(source) != graph.oppositeEdge(edge)) {
deba@1698
   204
	return false;
deba@1698
   205
      }
deba@1698
   206
      dfs.processNextEdge();
deba@1698
   207
    }
deba@1698
   208
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1698
   209
      if (!dfs.reached(it)) {
deba@1698
   210
	return false;
deba@1698
   211
      }
deba@1698
   212
    }    
deba@1698
   213
    return true;
deba@1698
   214
  }
deba@1698
   215
 
deba@1698
   216
deba@1698
   217
} //namespace lemon
deba@1698
   218
deba@1698
   219
#endif //LEMON_TOPOLOGY_H