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