lemon/topology.h
author alpar
Wed, 02 Nov 2005 16:43:18 +0000
changeset 1757 bd4199049036
parent 1740 4cade8579363
child 1763 49045f2d28d4
permissions -rw-r--r--
Spellcheck
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@1740
    21
#include <lemon/bfs.h>
deba@1698
    22
#include <lemon/graph_utils.h>
deba@1750
    23
#include <lemon/graph_adaptor.h>
deba@1750
    24
#include <lemon/maps.h>
deba@1698
    25
deba@1698
    26
#include <lemon/concept/graph.h>
deba@1698
    27
#include <lemon/concept/undir_graph.h>
deba@1698
    28
#include <lemon/concept_check.h>
deba@1698
    29
deba@1750
    30
#include <lemon/bin_heap.h>
deba@1750
    31
#include <lemon/linear_heap.h>
deba@1750
    32
deba@1750
    33
#include <stack>
deba@1750
    34
#include <functional>
deba@1750
    35
deba@1750
    36
/// \ingroup topology
deba@1698
    37
/// \file
deba@1698
    38
/// \brief Topology related algorithms
deba@1698
    39
///
deba@1698
    40
/// Topology related algorithms
deba@1698
    41
deba@1698
    42
namespace lemon {
deba@1698
    43
deba@1750
    44
  /// \ingroup topology
deba@1750
    45
  ///
deba@1750
    46
  /// \brief Check that the given undirected graph is connected.
deba@1750
    47
  ///
deba@1750
    48
  /// Check that the given undirected graph connected.
deba@1750
    49
  /// \param graph The undirected graph.
deba@1750
    50
  /// \return %True when there is path between any two nodes in the graph.
deba@1750
    51
  /// \warning The empty graph is not connected.
deba@1750
    52
  template <typename UndirGraph>
deba@1750
    53
  bool connected(const UndirGraph& graph) {
deba@1750
    54
    checkConcept<concept::UndirGraph, UndirGraph>();
deba@1750
    55
    typedef typename UndirGraph::NodeIt NodeIt;
deba@1750
    56
    if (NodeIt(graph) == INVALID) return false;
deba@1750
    57
    Dfs<UndirGraph> dfs(graph);
deba@1750
    58
    dfs.run(NodeIt(graph));
deba@1750
    59
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1750
    60
      if (!dfs.reached(it)) {
deba@1750
    61
	return false;
deba@1750
    62
      }
deba@1750
    63
    }
deba@1750
    64
    return true;
deba@1750
    65
  }
deba@1750
    66
deba@1750
    67
  /// \ingroup topology
deba@1750
    68
  ///
deba@1750
    69
  /// \brief Count the number of connected components of an undirected graph
deba@1750
    70
  ///
deba@1750
    71
  /// Count the number of connected components of an undirected graph
deba@1750
    72
  ///
deba@1750
    73
  /// \param g The graph. In must be undirected.
deba@1750
    74
  /// \return The number of components
deba@1750
    75
  template <typename UndirGraph>
deba@1750
    76
  int countConnectedComponents(const UndirGraph &graph) {
deba@1750
    77
    checkConcept<concept::UndirGraph, UndirGraph>();
deba@1750
    78
    typedef typename UndirGraph::Node Node;
deba@1750
    79
    typedef typename UndirGraph::Edge Edge;
deba@1750
    80
deba@1750
    81
    typedef NullMap<Node, Edge> PredMap;
deba@1750
    82
    typedef NullMap<Node, int> DistMap;
deba@1750
    83
deba@1750
    84
    int compNum = 0;
deba@1750
    85
    typename Bfs<UndirGraph>::
deba@1750
    86
      template DefPredMap<PredMap>::
deba@1750
    87
      template DefDistMap<DistMap>::
deba@1750
    88
      Create bfs(graph);
deba@1750
    89
deba@1750
    90
    PredMap predMap;
deba@1750
    91
    bfs.predMap(predMap);
deba@1750
    92
deba@1750
    93
    DistMap distMap;
deba@1750
    94
    bfs.distMap(distMap);
deba@1750
    95
deba@1750
    96
    bfs.init();
deba@1750
    97
    for(typename UndirGraph::NodeIt n(graph); n != INVALID; ++n) {
deba@1750
    98
      if (!bfs.reached(n)) {
deba@1750
    99
	bfs.addSource(n);
deba@1750
   100
	bfs.start();
deba@1750
   101
	++compNum;
deba@1750
   102
      }
deba@1750
   103
    }
deba@1750
   104
    return compNum;
deba@1750
   105
  }
deba@1750
   106
deba@1750
   107
  /// \ingroup topology
deba@1750
   108
  ///
deba@1750
   109
  /// \brief Find the connected components of an undirected graph
deba@1750
   110
  ///
deba@1750
   111
  /// Find the connected components of an undirected graph.
deba@1750
   112
  ///
deba@1750
   113
  /// \param g The graph. In must be undirected.
deba@1750
   114
  /// \retval comp A writable node map. The values will be set from 0 to
deba@1750
   115
  /// the number of the connected components minus one. Each values of the map
deba@1750
   116
  /// will be set exactly once, the values of a certain component will be
deba@1750
   117
  /// set continuously.
deba@1750
   118
  /// \return The number of components
deba@1750
   119
  template <class UndirGraph, class NodeMap>
deba@1750
   120
  int connectedComponents(const UndirGraph &graph, NodeMap &compMap) {
deba@1750
   121
    checkConcept<concept::UndirGraph, UndirGraph>();
deba@1750
   122
    typedef typename UndirGraph::Node Node;
deba@1750
   123
    typedef typename UndirGraph::Edge Edge;
deba@1750
   124
    checkConcept<concept::WriteMap<Node, int>, NodeMap>();
deba@1750
   125
deba@1750
   126
    typedef NullMap<Node, Edge> PredMap;
deba@1750
   127
    typedef NullMap<Node, int> DistMap;
deba@1750
   128
deba@1750
   129
    int compNum = 0;
deba@1750
   130
    typename Bfs<UndirGraph>::
deba@1750
   131
      template DefPredMap<PredMap>::
deba@1750
   132
      template DefDistMap<DistMap>::
deba@1750
   133
      Create bfs(graph);
deba@1750
   134
deba@1750
   135
    PredMap predMap;
deba@1750
   136
    bfs.predMap(predMap);
deba@1750
   137
deba@1750
   138
    DistMap distMap;
deba@1750
   139
    bfs.distMap(distMap);
deba@1750
   140
    
deba@1750
   141
    bfs.init();
deba@1750
   142
    for(typename UndirGraph::NodeIt n(graph); n != INVALID; ++n) {
deba@1750
   143
      if(!bfs.reached(n)) {
deba@1750
   144
	bfs.addSource(n);
deba@1750
   145
	while (!bfs.emptyQueue()) {
deba@1750
   146
	  compMap.set(bfs.nextNode(), compNum);
deba@1750
   147
	  bfs.processNextNode();
deba@1750
   148
	}
deba@1750
   149
	++compNum;
deba@1750
   150
      }
deba@1750
   151
    }
deba@1750
   152
    return compNum;
deba@1750
   153
  }
deba@1750
   154
deba@1750
   155
  namespace _topology_bits {
deba@1750
   156
deba@1750
   157
    template <typename Graph, typename Iterator >
deba@1750
   158
    struct LeaveOrderVisitor : public DfsVisitor<Graph> {
deba@1750
   159
    public:
deba@1750
   160
      typedef typename Graph::Node Node;
deba@1750
   161
      LeaveOrderVisitor(Iterator it) : _it(it) {}
deba@1750
   162
deba@1750
   163
      void leave(const Node& node) {
deba@1750
   164
	*(_it++) = node;
deba@1750
   165
      }
deba@1750
   166
deba@1750
   167
    private:
deba@1750
   168
      Iterator _it;
deba@1750
   169
    };
deba@1750
   170
deba@1750
   171
    template <typename Graph, typename Map>
deba@1750
   172
    struct FillMapVisitor : public DfsVisitor<Graph> {
deba@1750
   173
    public:
deba@1750
   174
      typedef typename Graph::Node Node;
deba@1750
   175
      typedef typename Map::Value Value;
deba@1750
   176
deba@1750
   177
      FillMapVisitor(Map& map, Value& value) 
deba@1750
   178
	: _map(map), _value(value) {}
deba@1750
   179
deba@1750
   180
      void reach(const Node& node) {
deba@1750
   181
	_map.set(node, _value);
deba@1750
   182
      }
deba@1750
   183
    private:
deba@1750
   184
      Map& _map;
deba@1750
   185
      Value& _value;
deba@1750
   186
    };
deba@1750
   187
deba@1750
   188
    template <typename Graph, typename EdgeMap>
deba@1750
   189
    struct StronglyConnectedCutEdgesVisitor : public DfsVisitor<Graph> {
deba@1750
   190
    public:
deba@1750
   191
      typedef typename Graph::Node Node;
deba@1750
   192
      typedef typename Graph::Edge Edge;
deba@1750
   193
deba@1750
   194
      StronglyConnectedCutEdgesVisitor(const Graph& graph, EdgeMap& cutMap, 
deba@1750
   195
				       int& cutNum) 
deba@1750
   196
	: _graph(graph), _cutMap(cutMap), _cutNum(cutNum), 
deba@1750
   197
	  _compMap(graph), _num(0) {
deba@1750
   198
      }
deba@1750
   199
deba@1750
   200
      void stop(const Node&) {
deba@1750
   201
	++_num;
deba@1750
   202
      }
deba@1750
   203
deba@1750
   204
      void reach(const Node& node) {
deba@1750
   205
	_compMap.set(node, _num);
deba@1750
   206
      }
deba@1750
   207
deba@1750
   208
      void examine(const Edge& edge) {
deba@1750
   209
 	if (_compMap[_graph.source(edge)] != _compMap[_graph.target(edge)]) {
deba@1750
   210
 	  _cutMap.set(edge, true);
deba@1750
   211
 	  ++_cutNum;
deba@1750
   212
 	}
deba@1750
   213
      }
deba@1750
   214
    private:
deba@1750
   215
      const Graph& _graph;
deba@1750
   216
      EdgeMap& _cutMap;
deba@1750
   217
      int& _cutNum;
deba@1750
   218
deba@1750
   219
      typename Graph::template NodeMap<int> _compMap;
deba@1750
   220
      int _num;
deba@1750
   221
    };
deba@1750
   222
deba@1750
   223
  }
deba@1750
   224
deba@1750
   225
deba@1750
   226
  /// \ingroup topology
deba@1750
   227
  ///
deba@1750
   228
  /// \brief Check that the given directed graph is strongly connected.
deba@1750
   229
  ///
deba@1750
   230
  /// Check that the given directed graph is strongly connected. The
deba@1750
   231
  /// graph is strongly connected when any two nodes of the graph are
deba@1750
   232
  /// connected with directed pathes in both direction.
deba@1750
   233
  /// \return %False when the graph is not strongly connected.
deba@1750
   234
  /// \see connected
deba@1750
   235
  ///
deba@1750
   236
  /// \waning Empty graph is not strongly connected.
deba@1750
   237
  template <typename Graph>
deba@1750
   238
  bool stronglyConnected(const Graph& graph) {
deba@1750
   239
    checkConcept<concept::StaticGraph, Graph>();
deba@1750
   240
    if (NodeIt(graph) == INVALID) return false;
deba@1750
   241
deba@1750
   242
    typedef typename Graph::Node Node;
deba@1750
   243
    typedef typename Graph::NodeIt NodeIt;
deba@1750
   244
deba@1750
   245
    using namespace _topology_bits;
deba@1750
   246
deba@1750
   247
    typedef DfsVisitor<Graph> Visitor;
deba@1750
   248
    Visitor visitor;
deba@1750
   249
deba@1750
   250
    DfsVisit<Graph, Visitor> dfs(graph, visitor);
deba@1750
   251
    dfs.init();
deba@1750
   252
    dfs.addSource(NodeIt(graph));
deba@1750
   253
    dfs.start();
deba@1750
   254
deba@1750
   255
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1750
   256
      if (!dfs.reached(it)) {
deba@1750
   257
	return false;
deba@1750
   258
      }
deba@1750
   259
    }
deba@1750
   260
deba@1750
   261
    typedef RevGraphAdaptor<const Graph> RGraph;
deba@1750
   262
    RGraph rgraph(graph);
deba@1750
   263
deba@1750
   264
    typedef DfsVisitor<Graph> RVisitor;
deba@1750
   265
    RVisitor rvisitor;
deba@1750
   266
deba@1750
   267
    DfsVisit<RGraph, RVisitor> rdfs(rgraph, rvisitor);
deba@1750
   268
    rdfs.init();    
deba@1750
   269
    rdfs.addSource(NodeIt(graph));
deba@1750
   270
    rdfs.start();
deba@1750
   271
deba@1750
   272
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1750
   273
      if (!rdfs.reached(it)) {
deba@1750
   274
	return false;
deba@1750
   275
      }
deba@1750
   276
    }
deba@1750
   277
deba@1750
   278
    return true;
deba@1750
   279
  }
deba@1750
   280
deba@1750
   281
  /// \ingroup topology
deba@1750
   282
  ///
deba@1750
   283
  /// \brief Count the strongly connected components of a directed graph
deba@1750
   284
  ///
deba@1750
   285
  /// Count the strongly connected components of a directed graph.
deba@1750
   286
  /// The strongly connected components are the classes of an equivalence
deba@1750
   287
  /// relation on the nodes of the graph. Two nodes are connected with
deba@1750
   288
  /// directed paths in both direction.
deba@1750
   289
  ///
deba@1750
   290
  /// \param g The graph.
deba@1750
   291
  /// \return The number of components
deba@1750
   292
  template <typename Graph>
deba@1750
   293
  int countStronglyConnectedComponents(const Graph& graph) {
deba@1750
   294
    checkConcept<concept::StaticGraph, Graph>();
deba@1750
   295
deba@1750
   296
    using namespace _topology_bits;
deba@1750
   297
deba@1750
   298
    typedef typename Graph::Node Node;
deba@1750
   299
    typedef typename Graph::Edge Edge;
deba@1750
   300
    typedef typename Graph::NodeIt NodeIt;
deba@1750
   301
    typedef typename Graph::EdgeIt EdgeIt;
deba@1750
   302
    
deba@1750
   303
    typedef std::vector<Node> Container;
deba@1750
   304
    typedef typename Container::iterator Iterator;
deba@1750
   305
deba@1750
   306
    Container nodes(countNodes(graph));
deba@1750
   307
    typedef LeaveOrderVisitor<Graph, Iterator> Visitor;
deba@1750
   308
    Visitor visitor(nodes.begin());
deba@1750
   309
      
deba@1750
   310
    DfsVisit<Graph, Visitor> dfs(graph, visitor);
deba@1750
   311
    dfs.init();
deba@1750
   312
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1750
   313
      if (!dfs.reached(it)) {
deba@1750
   314
	dfs.addSource(it);
deba@1750
   315
	dfs.start();
deba@1750
   316
      }
deba@1750
   317
    }
deba@1750
   318
deba@1750
   319
    typedef typename Container::reverse_iterator RIterator;
deba@1750
   320
    typedef RevGraphAdaptor<const Graph> RGraph;
deba@1750
   321
deba@1750
   322
    RGraph rgraph(graph);
deba@1750
   323
deba@1750
   324
    typedef DfsVisitor<Graph> RVisitor;
deba@1750
   325
    RVisitor rvisitor;
deba@1750
   326
deba@1750
   327
    DfsVisit<RGraph, RVisitor> rdfs(rgraph, rvisitor);
deba@1750
   328
deba@1750
   329
    int compNum = 0;
deba@1750
   330
deba@1750
   331
    rdfs.init();
deba@1750
   332
    for (RIterator it = nodes.rbegin(); it != nodes.rend(); ++it) {
deba@1750
   333
      if (!rdfs.reached(*it)) {
deba@1750
   334
	rdfs.addSource(*it);
deba@1750
   335
	rdfs.start();
deba@1750
   336
	++compNum;
deba@1750
   337
      }
deba@1750
   338
    }
deba@1750
   339
    return compNum;
deba@1750
   340
  }
deba@1750
   341
deba@1750
   342
  /// \ingroup topology
deba@1750
   343
  ///
deba@1750
   344
  /// \brief Find the strongly connected components of a directed graph
deba@1750
   345
  ///
deba@1750
   346
  /// Find the strongly connected components of a directed graph.
deba@1750
   347
  /// The strongly connected components are the classes of an equivalence
deba@1750
   348
  /// relation on the nodes of the graph. Two nodes are in relationship
deba@1750
   349
  /// when there are directed paths between them in both direction.
deba@1750
   350
  ///
deba@1750
   351
  /// \param g The graph.
deba@1750
   352
  /// \retval comp A writable node map. The values will be set from 0 to
deba@1750
   353
  /// the number of the strongly connected components minus one. Each values 
deba@1750
   354
  /// of the map will be set exactly once, the values of a certain component 
deba@1750
   355
  /// will be set continuously.
deba@1750
   356
  /// \return The number of components
deba@1750
   357
  template <typename Graph, typename NodeMap>
deba@1750
   358
  int stronglyConnectedComponents(const Graph& graph, NodeMap& compMap) {
deba@1750
   359
    checkConcept<concept::StaticGraph, Graph>();
deba@1750
   360
    typedef typename Graph::Node Node;
deba@1750
   361
    typedef typename Graph::NodeIt NodeIt;
deba@1750
   362
    checkConcept<concept::WriteMap<Node, int>, NodeMap>();
deba@1750
   363
deba@1750
   364
    using namespace _topology_bits;
deba@1750
   365
    
deba@1750
   366
    typedef std::vector<Node> Container;
deba@1750
   367
    typedef typename Container::iterator Iterator;
deba@1750
   368
deba@1750
   369
    Container nodes(countNodes(graph));
deba@1750
   370
    typedef LeaveOrderVisitor<Graph, Iterator> Visitor;
deba@1750
   371
    Visitor visitor(nodes.begin());
deba@1750
   372
      
deba@1750
   373
    DfsVisit<Graph, Visitor> dfs(graph, visitor);
deba@1750
   374
    dfs.init();
deba@1750
   375
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1750
   376
      if (!dfs.reached(it)) {
deba@1750
   377
	dfs.addSource(it);
deba@1750
   378
	dfs.start();
deba@1750
   379
      }
deba@1750
   380
    }
deba@1750
   381
deba@1750
   382
    typedef typename Container::reverse_iterator RIterator;
deba@1750
   383
    typedef RevGraphAdaptor<const Graph> RGraph;
deba@1750
   384
deba@1750
   385
    RGraph rgraph(graph);
deba@1750
   386
deba@1750
   387
    int compNum = 0;
deba@1750
   388
deba@1750
   389
    typedef FillMapVisitor<RGraph, NodeMap> RVisitor;
deba@1750
   390
    RVisitor rvisitor(compMap, compNum);
deba@1750
   391
deba@1750
   392
    DfsVisit<RGraph, RVisitor> rdfs(rgraph, rvisitor);
deba@1750
   393
deba@1750
   394
    rdfs.init();
deba@1750
   395
    for (RIterator it = nodes.rbegin(); it != nodes.rend(); ++it) {
deba@1750
   396
      if (!rdfs.reached(*it)) {
deba@1750
   397
	rdfs.addSource(*it);
deba@1750
   398
	rdfs.start();
deba@1750
   399
	++compNum;
deba@1750
   400
      }
deba@1750
   401
    }
deba@1750
   402
    return compNum;
deba@1750
   403
  }
deba@1750
   404
deba@1750
   405
  /// \ingroup topology
deba@1750
   406
  ///
deba@1750
   407
  /// \brief Find the cut edges of the strongly connected components.
deba@1750
   408
  ///
deba@1750
   409
  /// Find the cut edges of the strongly connected components.
deba@1750
   410
  /// The strongly connected components are the classes of an equivalence
deba@1750
   411
  /// relation on the nodes of the graph. Two nodes are in relationship
deba@1750
   412
  /// when there are directed paths between them in both direction.
deba@1750
   413
  /// The strongly connected components are separated by the cut edges.
deba@1750
   414
  ///
deba@1750
   415
  /// \param g The graph.
deba@1750
   416
  /// \retval comp A writable edge map. The values will be set true when
deba@1750
   417
  /// the edge is cut edge otherwise false.
deba@1750
   418
  ///
deba@1750
   419
  /// \return The number of cut edges
deba@1750
   420
  template <typename Graph, typename EdgeMap>
deba@1750
   421
  int stronglyConnectedCutEdges(const Graph& graph, EdgeMap& cutMap) {
deba@1750
   422
    checkConcept<concept::StaticGraph, Graph>();
deba@1750
   423
    typedef typename Graph::Node Node;
deba@1750
   424
    typedef typename Graph::Edge Edge;
deba@1750
   425
    typedef typename Graph::NodeIt NodeIt;
deba@1750
   426
    checkConcept<concept::WriteMap<Edge, bool>, EdgeMap>();
deba@1750
   427
deba@1750
   428
    using namespace _topology_bits;
deba@1750
   429
    
deba@1750
   430
    typedef std::vector<Node> Container;
deba@1750
   431
    typedef typename Container::iterator Iterator;
deba@1750
   432
deba@1750
   433
    Container nodes(countNodes(graph));
deba@1750
   434
    typedef LeaveOrderVisitor<Graph, Iterator> Visitor;
deba@1750
   435
    Visitor visitor(nodes.begin());
deba@1750
   436
      
deba@1750
   437
    DfsVisit<Graph, Visitor> dfs(graph, visitor);
deba@1750
   438
    dfs.init();
deba@1750
   439
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1750
   440
      if (!dfs.reached(it)) {
deba@1750
   441
	dfs.addSource(it);
deba@1750
   442
	dfs.start();
deba@1750
   443
      }
deba@1750
   444
    }
deba@1750
   445
deba@1750
   446
    typedef typename Container::reverse_iterator RIterator;
deba@1750
   447
    typedef RevGraphAdaptor<const Graph> RGraph;
deba@1750
   448
deba@1750
   449
    RGraph rgraph(graph);
deba@1750
   450
deba@1750
   451
    int cutNum = 0;
deba@1750
   452
deba@1750
   453
    typedef StronglyConnectedCutEdgesVisitor<RGraph, EdgeMap> RVisitor;
deba@1750
   454
    RVisitor rvisitor(rgraph, cutMap, cutNum);
deba@1750
   455
deba@1750
   456
    DfsVisit<RGraph, RVisitor> rdfs(rgraph, rvisitor);
deba@1750
   457
deba@1750
   458
    rdfs.init();
deba@1750
   459
    for (RIterator it = nodes.rbegin(); it != nodes.rend(); ++it) {
deba@1750
   460
      if (!rdfs.reached(*it)) {
deba@1750
   461
	rdfs.addSource(*it);
deba@1750
   462
	rdfs.start();
deba@1750
   463
      }
deba@1750
   464
    }
deba@1750
   465
    return cutNum;
deba@1750
   466
  }
deba@1750
   467
deba@1698
   468
  namespace _topology_bits {
deba@1698
   469
    
deba@1750
   470
    template <typename Graph>
deba@1750
   471
    class CountNodeBiconnectedComponentsVisitor : public DfsVisitor<Graph> {
deba@1698
   472
    public:
deba@1750
   473
      typedef typename Graph::Node Node;
deba@1750
   474
      typedef typename Graph::Edge Edge;
deba@1750
   475
      typedef typename Graph::UndirEdge UndirEdge;
deba@1698
   476
deba@1750
   477
      CountNodeBiconnectedComponentsVisitor(const Graph& graph, int &compNum) 
deba@1750
   478
	: _graph(graph), _compNum(compNum), 
deba@1750
   479
	  _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
deba@1750
   480
deba@1750
   481
      void start(const Node& node) {
deba@1750
   482
	_predMap.set(node, INVALID);
deba@1750
   483
      }
deba@1750
   484
      
deba@1750
   485
      void reach(const Node& node) {
deba@1750
   486
	_numMap.set(node, _num);
deba@1750
   487
	_retMap.set(node, _num);
deba@1750
   488
	++_num;
deba@1750
   489
      }
deba@1750
   490
deba@1750
   491
      void discover(const Edge& edge) {
deba@1750
   492
	_predMap.set(_graph.target(edge), _graph.source(edge));
deba@1750
   493
      }
deba@1750
   494
deba@1750
   495
      void examine(const Edge& edge) {
deba@1750
   496
	if (_graph.source(edge) == _graph.target(edge) && 
deba@1750
   497
	    _graph.direction(edge)) {
deba@1750
   498
	  ++_compNum;
deba@1750
   499
	  return;
deba@1750
   500
	}
deba@1750
   501
	if (_predMap[_graph.source(edge)] == _graph.target(edge)) {
deba@1750
   502
	  return;
deba@1750
   503
	}
deba@1750
   504
	if (_retMap[_graph.source(edge)] > _numMap[_graph.target(edge)]) {
deba@1750
   505
	  _retMap.set(_graph.source(edge), _numMap[_graph.target(edge)]);
deba@1698
   506
	}
deba@1698
   507
      }
deba@1698
   508
deba@1750
   509
      void backtrack(const Edge& edge) {
deba@1750
   510
	if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
deba@1750
   511
	  _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
deba@1750
   512
	}  
deba@1750
   513
	if (_numMap[_graph.source(edge)] <= _retMap[_graph.target(edge)]) {
deba@1750
   514
	  ++_compNum;
deba@1750
   515
	}
deba@1750
   516
      }
deba@1750
   517
      
deba@1750
   518
    private:
deba@1750
   519
      const Graph& _graph;
deba@1750
   520
      int& _compNum; 
deba@1750
   521
deba@1750
   522
      typename Graph::template NodeMap<int> _numMap;
deba@1750
   523
      typename Graph::template NodeMap<int> _retMap;
deba@1750
   524
      typename Graph::template NodeMap<Node> _predMap;
deba@1750
   525
      int _num;
deba@1750
   526
    };
deba@1750
   527
deba@1750
   528
    template <typename Graph, typename EdgeMap>
deba@1750
   529
    class NodeBiconnectedComponentsVisitor : public DfsVisitor<Graph> {
deba@1750
   530
    public:
deba@1750
   531
      typedef typename Graph::Node Node;
deba@1750
   532
      typedef typename Graph::Edge Edge;
deba@1750
   533
      typedef typename Graph::UndirEdge UndirEdge;
deba@1750
   534
deba@1750
   535
      NodeBiconnectedComponentsVisitor(const Graph& graph, 
deba@1750
   536
				       EdgeMap& compMap, int &compNum) 
deba@1750
   537
	: _graph(graph), _compMap(compMap), _compNum(compNum), 
deba@1750
   538
	  _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
deba@1750
   539
deba@1750
   540
      void start(const Node& node) {
deba@1750
   541
	_predMap.set(node, INVALID);
deba@1750
   542
      }
deba@1750
   543
      
deba@1750
   544
      void reach(const Node& node) {
deba@1750
   545
	_numMap.set(node, _num);
deba@1750
   546
	_retMap.set(node, _num);
deba@1750
   547
	++_num;
deba@1750
   548
      }
deba@1750
   549
deba@1750
   550
      void discover(const Edge& edge) {
deba@1750
   551
	Node target = _graph.target(edge);
deba@1750
   552
	_predMap.set(target, edge);
deba@1750
   553
	_edgeStack.push(edge);
deba@1750
   554
      }
deba@1750
   555
deba@1750
   556
      void examine(const Edge& edge) {
deba@1750
   557
	Node source = _graph.source(edge);
deba@1750
   558
	Node target = _graph.target(edge);
deba@1750
   559
	if (source == target && _graph.direction(edge)) {
deba@1750
   560
	  _compMap.set(edge, _compNum);
deba@1750
   561
	  ++_compNum;
deba@1750
   562
	  return;
deba@1750
   563
	}
deba@1750
   564
	if (_numMap[target] < _numMap[source]) {
deba@1750
   565
	  if (_predMap[source] != _graph.oppositeEdge(edge)) {
deba@1750
   566
	    _edgeStack.push(edge);
deba@1750
   567
	  }
deba@1750
   568
	}
deba@1750
   569
	if (_predMap[source] != INVALID && 
deba@1750
   570
	    target == _graph.source(_predMap[source])) {
deba@1750
   571
	  return;
deba@1750
   572
	}
deba@1750
   573
	if (_retMap[source] > _numMap[target]) {
deba@1750
   574
	  _retMap.set(source, _numMap[target]);
deba@1750
   575
	}
deba@1750
   576
      }
deba@1750
   577
deba@1750
   578
      void backtrack(const Edge& edge) {
deba@1750
   579
	Node source = _graph.source(edge);
deba@1750
   580
	Node target = _graph.target(edge);
deba@1750
   581
	if (_retMap[source] > _retMap[target]) {
deba@1750
   582
	  _retMap.set(source, _retMap[target]);
deba@1750
   583
	}  
deba@1750
   584
	if (_numMap[source] <= _retMap[target]) {
deba@1750
   585
	  while (_edgeStack.top() != edge) {
deba@1750
   586
	    _compMap.set(_edgeStack.top(), _compNum);
deba@1750
   587
	    _edgeStack.pop();
deba@1750
   588
	  }
deba@1750
   589
	  _compMap.set(edge, _compNum);
deba@1750
   590
	  _edgeStack.pop();
deba@1750
   591
	  ++_compNum;
deba@1750
   592
	}
deba@1750
   593
      }
deba@1750
   594
      
deba@1750
   595
    private:
deba@1750
   596
      const Graph& _graph;
deba@1750
   597
      EdgeMap& _compMap;
deba@1750
   598
      int& _compNum; 
deba@1750
   599
deba@1750
   600
      typename Graph::template NodeMap<int> _numMap;
deba@1750
   601
      typename Graph::template NodeMap<int> _retMap;
deba@1750
   602
      typename Graph::template NodeMap<Edge> _predMap;
deba@1750
   603
      std::stack<UndirEdge> _edgeStack;
deba@1750
   604
      int _num;
deba@1750
   605
    };
deba@1750
   606
deba@1750
   607
deba@1750
   608
    template <typename Graph, typename NodeMap>
deba@1750
   609
    class NodeBiconnectedCutNodesVisitor : public DfsVisitor<Graph> {
deba@1750
   610
    public:
deba@1750
   611
      typedef typename Graph::Node Node;
deba@1750
   612
      typedef typename Graph::Edge Edge;
deba@1750
   613
      typedef typename Graph::UndirEdge UndirEdge;
deba@1750
   614
deba@1750
   615
      NodeBiconnectedCutNodesVisitor(const Graph& graph, NodeMap& cutMap,
deba@1750
   616
				     int& cutNum) 
deba@1750
   617
	: _graph(graph), _cutMap(cutMap), _cutNum(cutNum),
deba@1750
   618
	  _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
deba@1750
   619
deba@1750
   620
      void start(const Node& node) {
deba@1750
   621
	_predMap.set(node, INVALID);
deba@1750
   622
	rootCut = false;
deba@1750
   623
      }
deba@1750
   624
      
deba@1750
   625
      void reach(const Node& node) {
deba@1750
   626
	_numMap.set(node, _num);
deba@1750
   627
	_retMap.set(node, _num);
deba@1750
   628
	++_num;
deba@1750
   629
      }
deba@1750
   630
deba@1750
   631
      void discover(const Edge& edge) {
deba@1750
   632
	_predMap.set(_graph.target(edge), _graph.source(edge));
deba@1750
   633
      }
deba@1750
   634
deba@1750
   635
      void examine(const Edge& edge) {
deba@1750
   636
	if (_graph.source(edge) == _graph.target(edge) && 
deba@1750
   637
	    _graph.direction(edge)) {
deba@1750
   638
	  if (!_cutMap[_graph.source(edge)]) {
deba@1750
   639
	    _cutMap.set(_graph.source(edge), true);
deba@1750
   640
	    ++_cutNum;
deba@1750
   641
	  }
deba@1750
   642
	  return;
deba@1750
   643
	}
deba@1750
   644
	if (_predMap[_graph.source(edge)] == _graph.target(edge)) return;
deba@1750
   645
	if (_retMap[_graph.source(edge)] > _numMap[_graph.target(edge)]) {
deba@1750
   646
	  _retMap.set(_graph.source(edge), _numMap[_graph.target(edge)]);
deba@1750
   647
	}
deba@1750
   648
      }
deba@1750
   649
deba@1750
   650
      void backtrack(const Edge& edge) {
deba@1750
   651
	if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
deba@1750
   652
	  _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
deba@1750
   653
	}  
deba@1750
   654
	if (_numMap[_graph.source(edge)] <= _retMap[_graph.target(edge)]) {
deba@1750
   655
	  if (_predMap[_graph.source(edge)] != INVALID) {
deba@1750
   656
	    if (!_cutMap[_graph.source(edge)]) {
deba@1750
   657
	      _cutMap.set(_graph.source(edge), true);
deba@1750
   658
	      ++_cutNum;
deba@1750
   659
	    }
deba@1750
   660
	  } else if (rootCut) {
deba@1750
   661
	    if (!_cutMap[_graph.source(edge)]) {
deba@1750
   662
	      _cutMap.set(_graph.source(edge), true);
deba@1750
   663
	      ++_cutNum;
deba@1750
   664
	    }
deba@1750
   665
	  } else {
deba@1750
   666
	    rootCut = true;
deba@1750
   667
	  }
deba@1750
   668
	}
deba@1750
   669
      }
deba@1750
   670
      
deba@1750
   671
    private:
deba@1750
   672
      const Graph& _graph;
deba@1750
   673
      NodeMap& _cutMap;
deba@1750
   674
      int& _cutNum; 
deba@1750
   675
deba@1750
   676
      typename Graph::template NodeMap<int> _numMap;
deba@1750
   677
      typename Graph::template NodeMap<int> _retMap;
deba@1750
   678
      typename Graph::template NodeMap<Node> _predMap;
deba@1750
   679
      std::stack<UndirEdge> _edgeStack;
deba@1750
   680
      int _num;
deba@1750
   681
      bool rootCut;
deba@1750
   682
    };
deba@1750
   683
deba@1750
   684
  }
deba@1750
   685
deba@1750
   686
  template <typename UndirGraph>
deba@1750
   687
  int countNodeBiconnectedComponents(const UndirGraph& graph);
deba@1750
   688
deba@1750
   689
  /// \ingroup topology
deba@1750
   690
  ///
deba@1750
   691
  /// \brief Checks the graph is node biconnected.
deba@1750
   692
  ///
deba@1750
   693
  /// This function checks that the undirected graph is node biconnected  
deba@1750
   694
  /// graph. The graph is node biconnected if any two undirected edge is 
deba@1750
   695
  /// on same circle.
deba@1750
   696
  ///
deba@1750
   697
  /// \param graph The graph.
deba@1750
   698
  /// \return %True when the graph node biconnected.
deba@1750
   699
  /// \todo Make it faster.
deba@1750
   700
  template <typename UndirGraph>
deba@1750
   701
  bool nodeBiconnected(const UndirGraph& graph) {
deba@1750
   702
    return countNodeBiconnectedComponents(graph) == 1;
deba@1750
   703
  }
deba@1750
   704
deba@1750
   705
  /// \ingroup topology
deba@1750
   706
  ///
deba@1750
   707
  /// \brief Count the biconnected components.
deba@1750
   708
  ///
deba@1750
   709
  /// This function finds the node biconnected components in an undirected 
deba@1750
   710
  /// graph. The biconnected components are the classes of an equivalence 
deba@1750
   711
  /// relation on the undirected edges. Two undirected edge is in relationship
deba@1750
   712
  /// when they are on same circle.
deba@1750
   713
  ///
deba@1750
   714
  /// \param graph The graph.
deba@1750
   715
  /// \return The number of components.
deba@1750
   716
  template <typename UndirGraph>
deba@1750
   717
  int countNodeBiconnectedComponents(const UndirGraph& graph) {
deba@1750
   718
    checkConcept<concept::UndirGraph, UndirGraph>();
deba@1750
   719
    typedef typename UndirGraph::NodeIt NodeIt;
deba@1750
   720
deba@1750
   721
    using namespace _topology_bits;
deba@1750
   722
deba@1750
   723
    typedef CountNodeBiconnectedComponentsVisitor<UndirGraph> Visitor;
deba@1750
   724
deba@1750
   725
    int compNum = 0;
deba@1750
   726
    Visitor visitor(graph, compNum);
deba@1750
   727
deba@1750
   728
    DfsVisit<UndirGraph, Visitor> dfs(graph, visitor);
deba@1750
   729
    dfs.init();
deba@1750
   730
    
deba@1750
   731
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1750
   732
      if (!dfs.reached(it)) {
deba@1750
   733
	dfs.addSource(it);
deba@1750
   734
	dfs.start();
deba@1750
   735
      }
deba@1750
   736
    }
deba@1750
   737
    return compNum;
deba@1750
   738
  }
deba@1750
   739
deba@1750
   740
  /// \ingroup topology
deba@1750
   741
  ///
deba@1750
   742
  /// \brief Find the node biconnected components.
deba@1750
   743
  ///
deba@1750
   744
  /// This function finds the node biconnected components in an undirected 
deba@1750
   745
  /// graph. The node biconnected components are the classes of an equivalence
deba@1750
   746
  /// relation on the undirected edges. Two undirected edge are in relationship
deba@1750
   747
  /// when they are on same circle.
deba@1750
   748
  ///
deba@1750
   749
  /// \param graph The graph.
deba@1750
   750
  /// \retval comp A writable undir edge map. The values will be set from 0 to
deba@1750
   751
  /// the number of the biconnected components minus one. Each values 
deba@1750
   752
  /// of the map will be set exactly once, the values of a certain component 
deba@1750
   753
  /// will be set continuously.
deba@1750
   754
  /// \return The number of components.
deba@1750
   755
  template <typename UndirGraph, typename UndirEdgeMap>
deba@1750
   756
  int nodeBiconnectedComponents(const UndirGraph& graph, 
deba@1750
   757
				UndirEdgeMap& compMap) {
deba@1750
   758
    checkConcept<concept::UndirGraph, UndirGraph>();
deba@1750
   759
    typedef typename UndirGraph::NodeIt NodeIt;
deba@1750
   760
    typedef typename UndirGraph::UndirEdge UndirEdge;
deba@1750
   761
    checkConcept<concept::WriteMap<UndirEdge, int>, UndirEdgeMap>();
deba@1750
   762
deba@1750
   763
    using namespace _topology_bits;
deba@1750
   764
deba@1750
   765
    typedef NodeBiconnectedComponentsVisitor<UndirGraph, UndirEdgeMap> Visitor;
deba@1750
   766
    
deba@1750
   767
    int compNum = 0;
deba@1750
   768
    Visitor visitor(graph, compMap, compNum);
deba@1750
   769
deba@1750
   770
    DfsVisit<UndirGraph, Visitor> dfs(graph, visitor);
deba@1750
   771
    dfs.init();
deba@1750
   772
    
deba@1750
   773
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1750
   774
      if (!dfs.reached(it)) {
deba@1750
   775
	dfs.addSource(it);
deba@1750
   776
	dfs.start();
deba@1750
   777
      }
deba@1750
   778
    }
deba@1750
   779
    return compNum;
deba@1750
   780
  }
deba@1750
   781
deba@1750
   782
  /// \ingroup topology
deba@1750
   783
  ///
deba@1750
   784
  /// \brief Find the node biconnected cut nodes.
deba@1750
   785
  ///
deba@1750
   786
  /// This function finds the node biconnected cut nodes in an undirected 
deba@1750
   787
  /// graph. The node biconnected components are the classes of an equivalence
deba@1750
   788
  /// relation on the undirected edges. Two undirected edges are in 
deba@1750
   789
  /// relationship when they are on same circle. The biconnected components 
deba@1750
   790
  /// are separted by nodes which are the cut nodes of the components.
deba@1750
   791
  ///
deba@1750
   792
  /// \param graph The graph.
deba@1750
   793
  /// \retval comp A writable edge map. The values will be set true when
deba@1750
   794
  /// the node separate two or more components.
deba@1750
   795
  /// \return The number of the cut nodes.
deba@1750
   796
  template <typename UndirGraph, typename NodeMap>
deba@1750
   797
  int nodeBiconnectedCutNodes(const UndirGraph& graph, NodeMap& cutMap) {
deba@1750
   798
    checkConcept<concept::UndirGraph, UndirGraph>();
deba@1750
   799
    typedef typename UndirGraph::Node Node;
deba@1750
   800
    typedef typename UndirGraph::NodeIt NodeIt;
deba@1750
   801
    checkConcept<concept::WriteMap<Node, bool>, NodeMap>();
deba@1750
   802
deba@1750
   803
    using namespace _topology_bits;
deba@1750
   804
deba@1750
   805
    typedef NodeBiconnectedCutNodesVisitor<UndirGraph, NodeMap> Visitor;
deba@1750
   806
    
deba@1750
   807
    int cutNum = 0;
deba@1750
   808
    Visitor visitor(graph, cutMap, cutNum);
deba@1750
   809
deba@1750
   810
    DfsVisit<UndirGraph, Visitor> dfs(graph, visitor);
deba@1750
   811
    dfs.init();
deba@1750
   812
    
deba@1750
   813
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1750
   814
      if (!dfs.reached(it)) {
deba@1750
   815
	dfs.addSource(it);
deba@1750
   816
	dfs.start();
deba@1750
   817
      }
deba@1750
   818
    }
deba@1750
   819
    return cutNum;
deba@1750
   820
  }
deba@1750
   821
deba@1750
   822
  namespace _topology_bits {
deba@1750
   823
    
deba@1750
   824
    template <typename Graph>
deba@1750
   825
    class CountEdgeBiconnectedComponentsVisitor : public DfsVisitor<Graph> {
deba@1750
   826
    public:
deba@1750
   827
      typedef typename Graph::Node Node;
deba@1750
   828
      typedef typename Graph::Edge Edge;
deba@1750
   829
      typedef typename Graph::UndirEdge UndirEdge;
deba@1750
   830
deba@1750
   831
      CountEdgeBiconnectedComponentsVisitor(const Graph& graph, int &compNum) 
deba@1750
   832
	: _graph(graph), _compNum(compNum), 
deba@1750
   833
	  _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
deba@1750
   834
deba@1750
   835
      void start(const Node& node) {
deba@1750
   836
	_predMap.set(node, INVALID);
deba@1750
   837
      }
deba@1750
   838
      
deba@1750
   839
      void reach(const Node& node) {
deba@1750
   840
	_numMap.set(node, _num);
deba@1750
   841
	_retMap.set(node, _num);
deba@1750
   842
	++_num;
deba@1750
   843
      }
deba@1750
   844
      
deba@1750
   845
      void leave(const Node& node) {
deba@1750
   846
	if (_numMap[node] <= _retMap[node]) {
deba@1750
   847
	  ++_compNum;
deba@1750
   848
	}	
deba@1750
   849
      }
deba@1750
   850
deba@1750
   851
      void discover(const Edge& edge) {
deba@1750
   852
	_predMap.set(_graph.target(edge), edge);
deba@1750
   853
      }
deba@1750
   854
deba@1750
   855
      void examine(const Edge& edge) {
deba@1750
   856
	if (_predMap[_graph.source(edge)] == _graph.oppositeEdge(edge)) {
deba@1750
   857
	  return;
deba@1750
   858
	}
deba@1750
   859
	if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
deba@1750
   860
	  _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
deba@1750
   861
	}
deba@1750
   862
      }
deba@1750
   863
deba@1750
   864
      void backtrack(const Edge& edge) {
deba@1750
   865
	if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
deba@1750
   866
	  _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
deba@1750
   867
	}  
deba@1750
   868
      }
deba@1750
   869
      
deba@1750
   870
    private:
deba@1750
   871
      const Graph& _graph;
deba@1750
   872
      int& _compNum; 
deba@1750
   873
deba@1750
   874
      typename Graph::template NodeMap<int> _numMap;
deba@1750
   875
      typename Graph::template NodeMap<int> _retMap;
deba@1750
   876
      typename Graph::template NodeMap<Edge> _predMap;
deba@1750
   877
      int _num;
deba@1750
   878
    };
deba@1750
   879
deba@1750
   880
    template <typename Graph, typename NodeMap>
deba@1750
   881
    class EdgeBiconnectedComponentsVisitor : public DfsVisitor<Graph> {
deba@1750
   882
    public:
deba@1750
   883
      typedef typename Graph::Node Node;
deba@1750
   884
      typedef typename Graph::Edge Edge;
deba@1750
   885
      typedef typename Graph::UndirEdge UndirEdge;
deba@1750
   886
deba@1750
   887
      EdgeBiconnectedComponentsVisitor(const Graph& graph, 
deba@1750
   888
				       NodeMap& compMap, int &compNum) 
deba@1750
   889
	: _graph(graph), _compMap(compMap), _compNum(compNum), 
deba@1750
   890
	  _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
deba@1750
   891
deba@1750
   892
      void start(const Node& node) {
deba@1750
   893
	_predMap.set(node, INVALID);
deba@1750
   894
      }
deba@1750
   895
      
deba@1750
   896
      void reach(const Node& node) {
deba@1750
   897
	_numMap.set(node, _num);
deba@1750
   898
	_retMap.set(node, _num);
deba@1750
   899
	_nodeStack.push(node);
deba@1750
   900
	++_num;
deba@1750
   901
      }
deba@1750
   902
      
deba@1750
   903
      void leave(const Node& node) {
deba@1750
   904
	if (_numMap[node] <= _retMap[node]) {
deba@1750
   905
	  while (_nodeStack.top() != node) {
deba@1750
   906
	    _compMap.set(_nodeStack.top(), _compNum);
deba@1750
   907
	    _nodeStack.pop();
deba@1750
   908
	  }
deba@1750
   909
	  _compMap.set(node, _compNum);
deba@1750
   910
	  _nodeStack.pop();
deba@1750
   911
	  ++_compNum;
deba@1750
   912
	}	
deba@1750
   913
      }
deba@1750
   914
deba@1750
   915
      void discover(const Edge& edge) {
deba@1750
   916
	_predMap.set(_graph.target(edge), edge);
deba@1750
   917
      }
deba@1750
   918
deba@1750
   919
      void examine(const Edge& edge) {
deba@1750
   920
	if (_predMap[_graph.source(edge)] == _graph.oppositeEdge(edge)) {
deba@1750
   921
	  return;
deba@1750
   922
	}
deba@1750
   923
	if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
deba@1750
   924
	  _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
deba@1750
   925
	}
deba@1750
   926
      }
deba@1750
   927
deba@1750
   928
      void backtrack(const Edge& edge) {
deba@1750
   929
	if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
deba@1750
   930
	  _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
deba@1750
   931
	}  
deba@1750
   932
      }
deba@1750
   933
      
deba@1750
   934
    private:
deba@1750
   935
      const Graph& _graph;
deba@1750
   936
      NodeMap& _compMap;
deba@1750
   937
      int& _compNum; 
deba@1750
   938
deba@1750
   939
      typename Graph::template NodeMap<int> _numMap;
deba@1750
   940
      typename Graph::template NodeMap<int> _retMap;
deba@1750
   941
      typename Graph::template NodeMap<Edge> _predMap;
deba@1750
   942
      std::stack<Node> _nodeStack;
deba@1750
   943
      int _num;
deba@1750
   944
    };
deba@1750
   945
deba@1750
   946
deba@1750
   947
    template <typename Graph, typename EdgeMap>
deba@1750
   948
    class EdgeBiconnectedCutEdgesVisitor : public DfsVisitor<Graph> {
deba@1750
   949
    public:
deba@1750
   950
      typedef typename Graph::Node Node;
deba@1750
   951
      typedef typename Graph::Edge Edge;
deba@1750
   952
      typedef typename Graph::UndirEdge UndirEdge;
deba@1750
   953
deba@1750
   954
      EdgeBiconnectedCutEdgesVisitor(const Graph& graph, 
deba@1750
   955
				     EdgeMap& cutMap, int &cutNum) 
deba@1750
   956
	: _graph(graph), _cutMap(cutMap), _cutNum(cutNum), 
deba@1750
   957
	  _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
deba@1750
   958
deba@1750
   959
      void start(const Node& node) {
deba@1750
   960
	_predMap[node] = INVALID;
deba@1750
   961
      }
deba@1750
   962
      
deba@1750
   963
      void reach(const Node& node) {
deba@1750
   964
	_numMap.set(node, _num);
deba@1750
   965
	_retMap.set(node, _num);
deba@1750
   966
	++_num;
deba@1750
   967
      }
deba@1750
   968
      
deba@1750
   969
      void leave(const Node& node) {
deba@1750
   970
	if (_numMap[node] <= _retMap[node]) {
deba@1750
   971
	  if (_predMap[node] != INVALID) {
deba@1750
   972
	    _cutMap.set(_predMap[node], true);
deba@1750
   973
	    ++_cutNum;
deba@1750
   974
	  }
deba@1750
   975
	}	
deba@1750
   976
      }
deba@1750
   977
deba@1750
   978
      void discover(const Edge& edge) {
deba@1750
   979
	_predMap.set(_graph.target(edge), edge);
deba@1750
   980
      }
deba@1750
   981
deba@1750
   982
      void examine(const Edge& edge) {
deba@1750
   983
	if (_predMap[_graph.source(edge)] == _graph.oppositeEdge(edge)) {
deba@1750
   984
	  return;
deba@1750
   985
	}
deba@1750
   986
	if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
deba@1750
   987
	  _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
deba@1750
   988
	}
deba@1750
   989
      }
deba@1750
   990
deba@1750
   991
      void backtrack(const Edge& edge) {
deba@1750
   992
	if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
deba@1750
   993
	  _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
deba@1750
   994
	}  
deba@1750
   995
      }
deba@1750
   996
      
deba@1750
   997
    private:
deba@1750
   998
      const Graph& _graph;
deba@1750
   999
      EdgeMap& _cutMap;
deba@1750
  1000
      int& _cutNum; 
deba@1750
  1001
deba@1750
  1002
      typename Graph::template NodeMap<int> _numMap;
deba@1750
  1003
      typename Graph::template NodeMap<int> _retMap;
deba@1750
  1004
      typename Graph::template NodeMap<Edge> _predMap;
deba@1750
  1005
      int _num;
deba@1750
  1006
    };
deba@1750
  1007
  }
deba@1750
  1008
deba@1750
  1009
  template <typename UndirGraph>
deba@1750
  1010
  int countEdgeBiconnectedComponents(const UndirGraph& graph);
deba@1750
  1011
deba@1750
  1012
  /// \ingroup topology
deba@1750
  1013
  ///
deba@1750
  1014
  /// \brief Checks that the graph is edge biconnected.
deba@1750
  1015
  ///
deba@1750
  1016
  /// This function checks that the graph is edge biconnected. The undirected
deba@1750
  1017
  /// graph is edge biconnected when any two nodes are connected with two
deba@1750
  1018
  /// edge-disjoint paths.
deba@1750
  1019
  ///
deba@1750
  1020
  /// \param graph The undirected graph.
deba@1750
  1021
  /// \return The number of components.
deba@1750
  1022
  /// \todo Make it faster.
deba@1750
  1023
  template <typename UndirGraph>
deba@1750
  1024
  bool edgeBiconnected(const UndirGraph& graph) { 
deba@1750
  1025
    return countEdgeBiconnectedComponents(graph) == 1;
deba@1750
  1026
  }
deba@1750
  1027
deba@1750
  1028
  /// \ingroup topology
deba@1750
  1029
  ///
deba@1750
  1030
  /// \brief Count the edge biconnected components.
deba@1750
  1031
  ///
deba@1750
  1032
  /// This function count the edge biconnected components in an undirected 
deba@1750
  1033
  /// graph. The edge biconnected components are the classes of an equivalence
deba@1750
  1034
  /// relation on the nodes. Two nodes are in relationship when they are  
deba@1750
  1035
  /// connected with at least two edge-disjoint paths.
deba@1750
  1036
  ///
deba@1750
  1037
  /// \param graph The undirected graph.
deba@1750
  1038
  /// \return The number of components.
deba@1750
  1039
  template <typename UndirGraph>
deba@1750
  1040
  int countEdgeBiconnectedComponents(const UndirGraph& graph) { 
deba@1750
  1041
    checkConcept<concept::UndirGraph, UndirGraph>();
deba@1750
  1042
    typedef typename UndirGraph::NodeIt NodeIt;
deba@1750
  1043
deba@1750
  1044
    using namespace _topology_bits;
deba@1750
  1045
deba@1750
  1046
    typedef CountEdgeBiconnectedComponentsVisitor<UndirGraph> Visitor;
deba@1750
  1047
    
deba@1750
  1048
    int compNum = 0;
deba@1750
  1049
    Visitor visitor(graph, compNum);
deba@1750
  1050
deba@1750
  1051
    DfsVisit<UndirGraph, Visitor> dfs(graph, visitor);
deba@1750
  1052
    dfs.init();
deba@1750
  1053
    
deba@1750
  1054
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1750
  1055
      if (!dfs.reached(it)) {
deba@1750
  1056
	dfs.addSource(it);
deba@1750
  1057
	dfs.start();
deba@1750
  1058
      }
deba@1750
  1059
    }
deba@1750
  1060
    return compNum;
deba@1750
  1061
  }
deba@1750
  1062
deba@1750
  1063
  /// \ingroup topology
deba@1750
  1064
  ///
deba@1750
  1065
  /// \brief Find the edge biconnected components.
deba@1750
  1066
  ///
deba@1750
  1067
  /// This function finds the edge biconnected components in an undirected 
deba@1750
  1068
  /// graph. The edge biconnected components are the classes of an equivalence
deba@1750
  1069
  /// relation on the nodes. Two nodes are in relationship when they are  
deba@1750
  1070
  /// connected at least two edge-disjoint paths.
deba@1750
  1071
  ///
deba@1750
  1072
  /// \param graph The graph.
deba@1750
  1073
  /// \retval comp A writable node map. The values will be set from 0 to
deba@1750
  1074
  /// the number of the biconnected components minus one. Each values 
deba@1750
  1075
  /// of the map will be set exactly once, the values of a certain component 
deba@1750
  1076
  /// will be set continuously.
deba@1750
  1077
  /// \return The number of components.
deba@1750
  1078
  template <typename UndirGraph, typename NodeMap>
deba@1750
  1079
  int edgeBiconnectedComponents(const UndirGraph& graph, NodeMap& compMap) { 
deba@1750
  1080
    checkConcept<concept::UndirGraph, UndirGraph>();
deba@1750
  1081
    typedef typename UndirGraph::NodeIt NodeIt;
deba@1750
  1082
    typedef typename UndirGraph::Node Node;
deba@1750
  1083
    checkConcept<concept::WriteMap<Node, int>, NodeMap>();
deba@1750
  1084
deba@1750
  1085
    using namespace _topology_bits;
deba@1750
  1086
deba@1750
  1087
    typedef EdgeBiconnectedComponentsVisitor<UndirGraph, NodeMap> Visitor;
deba@1750
  1088
    
deba@1750
  1089
    int compNum = 0;
deba@1750
  1090
    Visitor visitor(graph, compMap, compNum);
deba@1750
  1091
deba@1750
  1092
    DfsVisit<UndirGraph, Visitor> dfs(graph, visitor);
deba@1750
  1093
    dfs.init();
deba@1750
  1094
    
deba@1750
  1095
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1750
  1096
      if (!dfs.reached(it)) {
deba@1750
  1097
	dfs.addSource(it);
deba@1750
  1098
	dfs.start();
deba@1750
  1099
      }
deba@1750
  1100
    }
deba@1750
  1101
    return compNum;
deba@1750
  1102
  }
deba@1750
  1103
deba@1750
  1104
  /// \ingroup topology
deba@1750
  1105
  ///
deba@1750
  1106
  /// \brief Find the edge biconnected cut edges.
deba@1750
  1107
  ///
deba@1750
  1108
  /// This function finds the edge biconnected components in an undirected 
deba@1750
  1109
  /// graph. The edge biconnected components are the classes of an equivalence
deba@1750
  1110
  /// relation on the nodes. Two nodes are in relationship when they are 
deba@1750
  1111
  /// connected with at least two edge-disjoint paths. The edge biconnected 
deba@1750
  1112
  /// components are separted by edges which are the cut edges of the 
deba@1750
  1113
  /// components.
deba@1750
  1114
  ///
deba@1750
  1115
  /// \param graph The graph.
deba@1750
  1116
  /// \retval comp A writable node map. The values will be set true when the
deba@1750
  1117
  /// edge is a cut edge.
deba@1750
  1118
  /// \return The number of cut edges.
deba@1750
  1119
  template <typename UndirGraph, typename UndirEdgeMap>
deba@1750
  1120
  int edgeBiconnectedCutEdges(const UndirGraph& graph, UndirEdgeMap& cutMap) { 
deba@1750
  1121
    checkConcept<concept::UndirGraph, UndirGraph>();
deba@1750
  1122
    typedef typename UndirGraph::NodeIt NodeIt;
deba@1750
  1123
    typedef typename UndirGraph::UndirEdge UndirEdge;
deba@1750
  1124
    checkConcept<concept::WriteMap<UndirEdge, bool>, UndirEdgeMap>();
deba@1750
  1125
deba@1750
  1126
    using namespace _topology_bits;
deba@1750
  1127
deba@1750
  1128
    typedef EdgeBiconnectedCutEdgesVisitor<UndirGraph, UndirEdgeMap> Visitor;
deba@1750
  1129
    
deba@1750
  1130
    int cutNum = 0;
deba@1750
  1131
    Visitor visitor(graph, cutMap, cutNum);
deba@1750
  1132
deba@1750
  1133
    DfsVisit<UndirGraph, Visitor> dfs(graph, visitor);
deba@1750
  1134
    dfs.init();
deba@1750
  1135
    
deba@1750
  1136
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1750
  1137
      if (!dfs.reached(it)) {
deba@1750
  1138
	dfs.addSource(it);
deba@1750
  1139
	dfs.start();
deba@1750
  1140
      }
deba@1750
  1141
    }
deba@1750
  1142
    return cutNum;
deba@1750
  1143
  }
deba@1750
  1144
deba@1750
  1145
deba@1750
  1146
  namespace _topology_bits {
deba@1750
  1147
    
deba@1750
  1148
    template <typename Graph, typename IntNodeMap>
deba@1750
  1149
    class TopologicalSortVisitor : public DfsVisitor<Graph> {
deba@1750
  1150
    public:
deba@1750
  1151
      typedef typename Graph::Node Node;
deba@1750
  1152
      typedef typename Graph::Edge edge;
deba@1750
  1153
deba@1750
  1154
      TopologicalSortVisitor(IntNodeMap& order, int num) 
deba@1750
  1155
	: _order(order), _num(num) {}
deba@1750
  1156
      
deba@1750
  1157
      void leave(const Node& node) {
deba@1750
  1158
	_order.set(node, --_num);
deba@1698
  1159
      }
deba@1698
  1160
deba@1698
  1161
    private:
deba@1750
  1162
      IntNodeMap& _order;
deba@1750
  1163
      int _num;
deba@1698
  1164
    };
deba@1750
  1165
    
deba@1698
  1166
  }
deba@1698
  1167
deba@1750
  1168
  /// \ingroup topology
deba@1750
  1169
  ///
deba@1750
  1170
  /// \brief Sort the nodes of a DAG into topolgical order.
deba@1750
  1171
  ///
deba@1750
  1172
  /// Sort the nodes of a DAG into topolgical order.
deba@1750
  1173
  ///
deba@1750
  1174
  /// \param g The graph. In must be directed and acyclic.
deba@1750
  1175
  /// \retval comp A writable node map. The values will be set from 0 to
deba@1750
  1176
  /// the number of the nodes in the graph minus one. Each values of the map
deba@1750
  1177
  /// will be set exactly once, the values  will be set descending order.
deba@1750
  1178
  ///
deba@1750
  1179
  /// \see checkedTopologicalSort
deba@1750
  1180
  /// \see dag
deba@1698
  1181
  template <typename Graph, typename NodeMap>
deba@1750
  1182
  void topologicalSort(const Graph& graph, NodeMap& order) {
deba@1750
  1183
    using namespace _topology_bits;
deba@1750
  1184
deba@1750
  1185
    checkConcept<concept::StaticGraph, Graph>();
deba@1750
  1186
    checkConcept<concept::WriteMap<typename Graph::Node, int>, NodeMap>();
deba@1750
  1187
deba@1750
  1188
    typedef typename Graph::Node Node;
deba@1750
  1189
    typedef typename Graph::NodeIt NodeIt;
deba@1750
  1190
    typedef typename Graph::Edge Edge;
deba@1750
  1191
deba@1750
  1192
    TopologicalSortVisitor<Graph, NodeMap> 
deba@1750
  1193
      visitor(order, countNodes(graph)); 
deba@1750
  1194
deba@1750
  1195
    DfsVisit<Graph, TopologicalSortVisitor<Graph, NodeMap> >
deba@1750
  1196
      dfs(graph, visitor);
deba@1750
  1197
deba@1750
  1198
    dfs.init();
deba@1750
  1199
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1750
  1200
      if (!dfs.reached(it)) {
deba@1750
  1201
	dfs.addSource(it);
deba@1750
  1202
	dfs.start();
deba@1750
  1203
      }
deba@1750
  1204
    }    
deba@1750
  1205
  }
deba@1750
  1206
deba@1750
  1207
  /// \ingroup topology
deba@1750
  1208
  ///
deba@1750
  1209
  /// \brief Sort the nodes of a DAG into topolgical order.
deba@1750
  1210
  ///
deba@1750
  1211
  /// Sort the nodes of a DAG into topolgical order. It also checks
deba@1750
  1212
  /// that the given graph is DAG.
deba@1750
  1213
  ///
deba@1750
  1214
  /// \param g The graph. In must be directed and acyclic.
deba@1750
  1215
  /// \retval order A readable - writable node map. The values will be set 
deba@1750
  1216
  /// from 0 to the number of the nodes in the graph minus one. Each values 
deba@1750
  1217
  /// of the map will be set exactly once, the values will be set descending 
deba@1750
  1218
  /// order.
deba@1750
  1219
  /// \return %False when the graph is not DAG.
deba@1750
  1220
  ///
deba@1750
  1221
  /// \see topologicalSort
deba@1750
  1222
  /// \see dag
deba@1750
  1223
  template <typename Graph, typename NodeMap>
deba@1750
  1224
  bool checkedTopologicalSort(const Graph& graph, NodeMap& order) {
deba@1698
  1225
    using namespace _topology_bits;
deba@1698
  1226
deba@1698
  1227
    checkConcept<concept::StaticGraph, Graph>();
deba@1698
  1228
    checkConcept<concept::ReadWriteMap<typename Graph::Node, int>, NodeMap>();
deba@1698
  1229
deba@1698
  1230
    typedef typename Graph::Node Node;
deba@1698
  1231
    typedef typename Graph::NodeIt NodeIt;
deba@1698
  1232
    typedef typename Graph::Edge Edge;
deba@1698
  1233
deba@1750
  1234
    order = constMap<Node, int, -1>();
deba@1698
  1235
deba@1750
  1236
    TopologicalSortVisitor<Graph, NodeMap> 
deba@1750
  1237
      visitor(order, countNodes(graph)); 
deba@1698
  1238
deba@1750
  1239
    DfsVisit<Graph, TopologicalSortVisitor<Graph, NodeMap> >
deba@1750
  1240
      dfs(graph, visitor);
deba@1698
  1241
deba@1698
  1242
    dfs.init();
deba@1698
  1243
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1698
  1244
      if (!dfs.reached(it)) {
deba@1698
  1245
	dfs.addSource(it);
deba@1698
  1246
	while (!dfs.emptyQueue()) {
deba@1750
  1247
 	  Edge edge = dfs.nextEdge();
deba@1750
  1248
 	  Node target = graph.target(edge);
deba@1750
  1249
 	  if (dfs.reached(target) && order[target] == -1) {
deba@1750
  1250
 	    return false;
deba@1750
  1251
 	  }
deba@1750
  1252
 	  dfs.processNextEdge();
deba@1750
  1253
 	}
deba@1698
  1254
      }
deba@1750
  1255
    }
deba@1698
  1256
    return true;
deba@1698
  1257
  }
deba@1698
  1258
deba@1750
  1259
  /// \ingroup topology
deba@1698
  1260
  ///
deba@1750
  1261
  /// \brief Check that the given directed graph is a DAG.
deba@1750
  1262
  ///
deba@1750
  1263
  /// Check that the given directed graph is a DAG. The DAG is
deba@1698
  1264
  /// an Directed Acyclic Graph.
deba@1750
  1265
  /// \return %False when the graph is not DAG.
deba@1750
  1266
  /// \see acyclic
deba@1698
  1267
  template <typename Graph>
deba@1698
  1268
  bool dag(const Graph& graph) {
deba@1698
  1269
deba@1698
  1270
    checkConcept<concept::StaticGraph, Graph>();
deba@1698
  1271
deba@1698
  1272
    typedef typename Graph::Node Node;
deba@1698
  1273
    typedef typename Graph::NodeIt NodeIt;
deba@1698
  1274
    typedef typename Graph::Edge Edge;
deba@1698
  1275
deba@1698
  1276
    typedef typename Graph::template NodeMap<bool> ProcessedMap;
deba@1698
  1277
deba@1698
  1278
    typename Dfs<Graph>::template DefProcessedMap<ProcessedMap>::
deba@1709
  1279
      Create dfs(graph);
deba@1698
  1280
deba@1698
  1281
    ProcessedMap processed(graph);
deba@1698
  1282
    dfs.processedMap(processed);
deba@1698
  1283
deba@1698
  1284
    dfs.init();
deba@1698
  1285
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1698
  1286
      if (!dfs.reached(it)) {
deba@1698
  1287
	dfs.addSource(it);
deba@1698
  1288
	while (!dfs.emptyQueue()) {
deba@1698
  1289
	  Edge edge = dfs.nextEdge();
deba@1698
  1290
	  Node target = graph.target(edge);
deba@1698
  1291
	  if (dfs.reached(target) && !processed[target]) {
deba@1698
  1292
	    return false;
deba@1698
  1293
	  }
deba@1698
  1294
	  dfs.processNextEdge();
deba@1698
  1295
	}
deba@1698
  1296
      }
deba@1698
  1297
    }    
deba@1698
  1298
    return true;
deba@1698
  1299
  }
deba@1698
  1300
deba@1750
  1301
  /// \ingroup topology
deba@1698
  1302
  ///
deba@1698
  1303
  /// \brief Check that the given undirected graph is acyclic.
deba@1698
  1304
  ///
deba@1698
  1305
  /// Check that the given undirected graph acyclic.
deba@1750
  1306
  /// \param graph The undirected graph.
deba@1750
  1307
  /// \return %True when there is no circle in the graph.
deba@1750
  1308
  /// \see dag
deba@1698
  1309
  template <typename UndirGraph>
deba@1698
  1310
  bool acyclic(const UndirGraph& graph) {
deba@1698
  1311
    checkConcept<concept::UndirGraph, UndirGraph>();
deba@1698
  1312
    typedef typename UndirGraph::Node Node;
deba@1698
  1313
    typedef typename UndirGraph::NodeIt NodeIt;
deba@1698
  1314
    typedef typename UndirGraph::Edge Edge;
deba@1698
  1315
    Dfs<UndirGraph> dfs(graph);
deba@1698
  1316
    dfs.init();
deba@1698
  1317
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1698
  1318
      if (!dfs.reached(it)) {
deba@1698
  1319
	dfs.addSource(it);
deba@1698
  1320
	while (!dfs.emptyQueue()) {
deba@1698
  1321
	  Edge edge = dfs.nextEdge();
deba@1698
  1322
	  Node source = graph.source(edge);
deba@1698
  1323
	  Node target = graph.target(edge);
deba@1698
  1324
	  if (dfs.reached(target) && 
deba@1698
  1325
	      dfs.pred(source) != graph.oppositeEdge(edge)) {
deba@1698
  1326
	    return false;
deba@1698
  1327
	  }
deba@1698
  1328
	  dfs.processNextEdge();
deba@1698
  1329
	}
deba@1698
  1330
      }
deba@1698
  1331
    }
deba@1698
  1332
    return true;
deba@1698
  1333
  }
deba@1698
  1334
deba@1750
  1335
  /// \ingroup topology
deba@1750
  1336
  ///
deba@1698
  1337
  /// \brief Check that the given undirected graph is tree.
deba@1698
  1338
  ///
deba@1698
  1339
  /// Check that the given undirected graph is tree.
deba@1750
  1340
  /// \param graph The undirected graph.
deba@1750
  1341
  /// \return %True when the graph is acyclic and connected.
deba@1698
  1342
  template <typename UndirGraph>
deba@1698
  1343
  bool tree(const UndirGraph& graph) {
deba@1698
  1344
    checkConcept<concept::UndirGraph, UndirGraph>();
deba@1698
  1345
    typedef typename UndirGraph::Node Node;
deba@1698
  1346
    typedef typename UndirGraph::NodeIt NodeIt;
deba@1698
  1347
    typedef typename UndirGraph::Edge Edge;
deba@1698
  1348
    Dfs<UndirGraph> dfs(graph);
deba@1698
  1349
    dfs.init();
deba@1698
  1350
    dfs.addSource(NodeIt(graph));
deba@1698
  1351
    while (!dfs.emptyQueue()) {
deba@1698
  1352
      Edge edge = dfs.nextEdge();
deba@1698
  1353
      Node source = graph.source(edge);
deba@1698
  1354
      Node target = graph.target(edge);
deba@1698
  1355
      if (dfs.reached(target) && 
deba@1698
  1356
	  dfs.pred(source) != graph.oppositeEdge(edge)) {
deba@1698
  1357
	return false;
deba@1698
  1358
      }
deba@1698
  1359
      dfs.processNextEdge();
deba@1698
  1360
    }
deba@1698
  1361
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1698
  1362
      if (!dfs.reached(it)) {
deba@1698
  1363
	return false;
deba@1698
  1364
      }
deba@1698
  1365
    }    
deba@1698
  1366
    return true;
deba@1698
  1367
  }
alpar@1739
  1368
deba@1750
  1369
  /// \ingroup topology
alpar@1739
  1370
  ///
deba@1750
  1371
  /// \brief Check that the given undirected graph is bipartite.
deba@1750
  1372
  ///
deba@1750
  1373
  /// Check that the given undirected graph is bipartite.
deba@1750
  1374
  /// \param graph The undirected graph.
deba@1750
  1375
  /// \return %True when the nodes can be separated into two sets that
deba@1750
  1376
  /// there are not connected nodes in neither sets.
deba@1750
  1377
  template <typename UndirGraph>
deba@1750
  1378
  bool bipartite(const UndirGraph& graph) {
deba@1740
  1379
    checkConcept<concept::UndirGraph, UndirGraph>();
deba@1750
  1380
    typedef typename UndirGraph::Node Node;
deba@1750
  1381
    typedef typename UndirGraph::NodeIt NodeIt;
deba@1750
  1382
    typedef typename UndirGraph::Edge Edge;
deba@1750
  1383
    if (NodeIt(graph) == INVALID) return false;
deba@1750
  1384
    Dfs<UndirGraph> dfs(graph);
deba@1740
  1385
    dfs.init();
deba@1750
  1386
    typename UndirGraph::template NodeMap<bool> red(graph);
deba@1740
  1387
    for (NodeIt it(graph); it != INVALID; ++it) {
deba@1740
  1388
      if (!dfs.reached(it)) {
deba@1740
  1389
	dfs.addSource(it);
deba@1750
  1390
	red[it] = true;
deba@1750
  1391
	while (!dfs.emptyQueue()) {
deba@1750
  1392
	  Edge edge = dfs.nextEdge();
deba@1750
  1393
	  Node source = graph.source(edge);
deba@1750
  1394
	  Node target = graph.target(edge);
deba@1750
  1395
	  if (dfs.reached(target) && red[source] == red[target]) {
deba@1750
  1396
	    return false;
deba@1750
  1397
	  } else {
deba@1750
  1398
	    red[target] = !red[source];
deba@1750
  1399
	  }
deba@1750
  1400
	  dfs.processNextEdge();
deba@1750
  1401
	}
deba@1740
  1402
      }
deba@1740
  1403
    }
deba@1750
  1404
    return true;
deba@1740
  1405
  }
deba@1750
  1406
   
deba@1698
  1407
} //namespace lemon
deba@1698
  1408
deba@1698
  1409
#endif //LEMON_TOPOLOGY_H