lemon/topology.h
author hegyi
Mon, 21 Nov 2005 18:03:20 +0000
changeset 1823 cb082cdf3667
parent 1808 c499025ca638
child 1875 98698b69a902
permissions -rw-r--r--
NewMapWin has become Dialog instead of Window. Therefore it is created dynamically, when there is need for it, instead of keeping one instance in memory. This solution is slower, but more correct than before.
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.
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