COIN-OR::LEMON - Graph Library

source: lemon-1.2/lemon/connectivity.h @ 986:552e3d1242c6

Last change on this file since 986:552e3d1242c6 was 986:552e3d1242c6, checked in by Balazs Dezso <deba@…>, 6 years ago

Fix biNodeConnected() function (#439)

File size: 50.5 KB
Line 
1/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 *
3 * This file is a part of LEMON, a generic C++ optimization library.
4 *
5 * Copyright (C) 2003-2009
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 *
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
12 *
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
15 * purpose.
16 *
17 */
18
19#ifndef LEMON_CONNECTIVITY_H
20#define LEMON_CONNECTIVITY_H
21
22#include <lemon/dfs.h>
23#include <lemon/bfs.h>
24#include <lemon/core.h>
25#include <lemon/maps.h>
26#include <lemon/adaptors.h>
27
28#include <lemon/concepts/digraph.h>
29#include <lemon/concepts/graph.h>
30#include <lemon/concept_check.h>
31
32#include <stack>
33#include <functional>
34
35/// \ingroup graph_properties
36/// \file
37/// \brief Connectivity algorithms
38///
39/// Connectivity algorithms
40
41namespace lemon {
42
43  /// \ingroup graph_properties
44  ///
45  /// \brief Check whether an undirected graph is connected.
46  ///
47  /// This function checks whether the given undirected graph is connected,
48  /// i.e. there is a path between any two nodes in the graph.
49  ///
50  /// \return \c true if the graph is connected.
51  /// \note By definition, the empty graph is connected.
52  ///
53  /// \see countConnectedComponents(), connectedComponents()
54  /// \see stronglyConnected()
55  template <typename Graph>
56  bool connected(const Graph& graph) {
57    checkConcept<concepts::Graph, Graph>();
58    typedef typename Graph::NodeIt NodeIt;
59    if (NodeIt(graph) == INVALID) return true;
60    Dfs<Graph> dfs(graph);
61    dfs.run(NodeIt(graph));
62    for (NodeIt it(graph); it != INVALID; ++it) {
63      if (!dfs.reached(it)) {
64        return false;
65      }
66    }
67    return true;
68  }
69
70  /// \ingroup graph_properties
71  ///
72  /// \brief Count the number of connected components of an undirected graph
73  ///
74  /// This function counts the number of connected components of the given
75  /// undirected graph.
76  ///
77  /// The connected components are the classes of an equivalence relation
78  /// on the nodes of an undirected graph. Two nodes are in the same class
79  /// if they are connected with a path.
80  ///
81  /// \return The number of connected components.
82  /// \note By definition, the empty graph consists
83  /// of zero connected components.
84  ///
85  /// \see connected(), connectedComponents()
86  template <typename Graph>
87  int countConnectedComponents(const Graph &graph) {
88    checkConcept<concepts::Graph, Graph>();
89    typedef typename Graph::Node Node;
90    typedef typename Graph::Arc Arc;
91
92    typedef NullMap<Node, Arc> PredMap;
93    typedef NullMap<Node, int> DistMap;
94
95    int compNum = 0;
96    typename Bfs<Graph>::
97      template SetPredMap<PredMap>::
98      template SetDistMap<DistMap>::
99      Create bfs(graph);
100
101    PredMap predMap;
102    bfs.predMap(predMap);
103
104    DistMap distMap;
105    bfs.distMap(distMap);
106
107    bfs.init();
108    for(typename Graph::NodeIt n(graph); n != INVALID; ++n) {
109      if (!bfs.reached(n)) {
110        bfs.addSource(n);
111        bfs.start();
112        ++compNum;
113      }
114    }
115    return compNum;
116  }
117
118  /// \ingroup graph_properties
119  ///
120  /// \brief Find the connected components of an undirected graph
121  ///
122  /// This function finds the connected components of the given undirected
123  /// graph.
124  ///
125  /// The connected components are the classes of an equivalence relation
126  /// on the nodes of an undirected graph. Two nodes are in the same class
127  /// if they are connected with a path.
128  ///
129  /// \image html connected_components.png
130  /// \image latex connected_components.eps "Connected components" width=\textwidth
131  ///
132  /// \param graph The undirected graph.
133  /// \retval compMap A writable node map. The values will be set from 0 to
134  /// the number of the connected components minus one. Each value of the map
135  /// will be set exactly once, and the values of a certain component will be
136  /// set continuously.
137  /// \return The number of connected components.
138  /// \note By definition, the empty graph consists
139  /// of zero connected components.
140  ///
141  /// \see connected(), countConnectedComponents()
142  template <class Graph, class NodeMap>
143  int connectedComponents(const Graph &graph, NodeMap &compMap) {
144    checkConcept<concepts::Graph, Graph>();
145    typedef typename Graph::Node Node;
146    typedef typename Graph::Arc Arc;
147    checkConcept<concepts::WriteMap<Node, int>, NodeMap>();
148
149    typedef NullMap<Node, Arc> PredMap;
150    typedef NullMap<Node, int> DistMap;
151
152    int compNum = 0;
153    typename Bfs<Graph>::
154      template SetPredMap<PredMap>::
155      template SetDistMap<DistMap>::
156      Create bfs(graph);
157
158    PredMap predMap;
159    bfs.predMap(predMap);
160
161    DistMap distMap;
162    bfs.distMap(distMap);
163
164    bfs.init();
165    for(typename Graph::NodeIt n(graph); n != INVALID; ++n) {
166      if(!bfs.reached(n)) {
167        bfs.addSource(n);
168        while (!bfs.emptyQueue()) {
169          compMap.set(bfs.nextNode(), compNum);
170          bfs.processNextNode();
171        }
172        ++compNum;
173      }
174    }
175    return compNum;
176  }
177
178  namespace _connectivity_bits {
179
180    template <typename Digraph, typename Iterator >
181    struct LeaveOrderVisitor : public DfsVisitor<Digraph> {
182    public:
183      typedef typename Digraph::Node Node;
184      LeaveOrderVisitor(Iterator it) : _it(it) {}
185
186      void leave(const Node& node) {
187        *(_it++) = node;
188      }
189
190    private:
191      Iterator _it;
192    };
193
194    template <typename Digraph, typename Map>
195    struct FillMapVisitor : public DfsVisitor<Digraph> {
196    public:
197      typedef typename Digraph::Node Node;
198      typedef typename Map::Value Value;
199
200      FillMapVisitor(Map& map, Value& value)
201        : _map(map), _value(value) {}
202
203      void reach(const Node& node) {
204        _map.set(node, _value);
205      }
206    private:
207      Map& _map;
208      Value& _value;
209    };
210
211    template <typename Digraph, typename ArcMap>
212    struct StronglyConnectedCutArcsVisitor : public DfsVisitor<Digraph> {
213    public:
214      typedef typename Digraph::Node Node;
215      typedef typename Digraph::Arc Arc;
216
217      StronglyConnectedCutArcsVisitor(const Digraph& digraph,
218                                      ArcMap& cutMap,
219                                      int& cutNum)
220        : _digraph(digraph), _cutMap(cutMap), _cutNum(cutNum),
221          _compMap(digraph, -1), _num(-1) {
222      }
223
224      void start(const Node&) {
225        ++_num;
226      }
227
228      void reach(const Node& node) {
229        _compMap.set(node, _num);
230      }
231
232      void examine(const Arc& arc) {
233         if (_compMap[_digraph.source(arc)] !=
234             _compMap[_digraph.target(arc)]) {
235           _cutMap.set(arc, true);
236           ++_cutNum;
237         }
238      }
239    private:
240      const Digraph& _digraph;
241      ArcMap& _cutMap;
242      int& _cutNum;
243
244      typename Digraph::template NodeMap<int> _compMap;
245      int _num;
246    };
247
248  }
249
250
251  /// \ingroup graph_properties
252  ///
253  /// \brief Check whether a directed graph is strongly connected.
254  ///
255  /// This function checks whether the given directed graph is strongly
256  /// connected, i.e. any two nodes of the digraph are
257  /// connected with directed paths in both direction.
258  ///
259  /// \return \c true if the digraph is strongly connected.
260  /// \note By definition, the empty digraph is strongly connected.
261  ///
262  /// \see countStronglyConnectedComponents(), stronglyConnectedComponents()
263  /// \see connected()
264  template <typename Digraph>
265  bool stronglyConnected(const Digraph& digraph) {
266    checkConcept<concepts::Digraph, Digraph>();
267
268    typedef typename Digraph::Node Node;
269    typedef typename Digraph::NodeIt NodeIt;
270
271    typename Digraph::Node source = NodeIt(digraph);
272    if (source == INVALID) return true;
273
274    using namespace _connectivity_bits;
275
276    typedef DfsVisitor<Digraph> Visitor;
277    Visitor visitor;
278
279    DfsVisit<Digraph, Visitor> dfs(digraph, visitor);
280    dfs.init();
281    dfs.addSource(source);
282    dfs.start();
283
284    for (NodeIt it(digraph); it != INVALID; ++it) {
285      if (!dfs.reached(it)) {
286        return false;
287      }
288    }
289
290    typedef ReverseDigraph<const Digraph> RDigraph;
291    typedef typename RDigraph::NodeIt RNodeIt;
292    RDigraph rdigraph(digraph);
293
294    typedef DfsVisitor<RDigraph> RVisitor;
295    RVisitor rvisitor;
296
297    DfsVisit<RDigraph, RVisitor> rdfs(rdigraph, rvisitor);
298    rdfs.init();
299    rdfs.addSource(source);
300    rdfs.start();
301
302    for (RNodeIt it(rdigraph); it != INVALID; ++it) {
303      if (!rdfs.reached(it)) {
304        return false;
305      }
306    }
307
308    return true;
309  }
310
311  /// \ingroup graph_properties
312  ///
313  /// \brief Count the number of strongly connected components of a
314  /// directed graph
315  ///
316  /// This function counts the number of strongly connected components of
317  /// the given directed graph.
318  ///
319  /// The strongly connected components are the classes of an
320  /// equivalence relation on the nodes of a digraph. Two nodes are in
321  /// the same class if they are connected with directed paths in both
322  /// direction.
323  ///
324  /// \return The number of strongly connected components.
325  /// \note By definition, the empty digraph has zero
326  /// strongly connected components.
327  ///
328  /// \see stronglyConnected(), stronglyConnectedComponents()
329  template <typename Digraph>
330  int countStronglyConnectedComponents(const Digraph& digraph) {
331    checkConcept<concepts::Digraph, Digraph>();
332
333    using namespace _connectivity_bits;
334
335    typedef typename Digraph::Node Node;
336    typedef typename Digraph::Arc Arc;
337    typedef typename Digraph::NodeIt NodeIt;
338    typedef typename Digraph::ArcIt ArcIt;
339
340    typedef std::vector<Node> Container;
341    typedef typename Container::iterator Iterator;
342
343    Container nodes(countNodes(digraph));
344    typedef LeaveOrderVisitor<Digraph, Iterator> Visitor;
345    Visitor visitor(nodes.begin());
346
347    DfsVisit<Digraph, Visitor> dfs(digraph, visitor);
348    dfs.init();
349    for (NodeIt it(digraph); it != INVALID; ++it) {
350      if (!dfs.reached(it)) {
351        dfs.addSource(it);
352        dfs.start();
353      }
354    }
355
356    typedef typename Container::reverse_iterator RIterator;
357    typedef ReverseDigraph<const Digraph> RDigraph;
358
359    RDigraph rdigraph(digraph);
360
361    typedef DfsVisitor<Digraph> RVisitor;
362    RVisitor rvisitor;
363
364    DfsVisit<RDigraph, RVisitor> rdfs(rdigraph, rvisitor);
365
366    int compNum = 0;
367
368    rdfs.init();
369    for (RIterator it = nodes.rbegin(); it != nodes.rend(); ++it) {
370      if (!rdfs.reached(*it)) {
371        rdfs.addSource(*it);
372        rdfs.start();
373        ++compNum;
374      }
375    }
376    return compNum;
377  }
378
379  /// \ingroup graph_properties
380  ///
381  /// \brief Find the strongly connected components of a directed graph
382  ///
383  /// This function finds the strongly connected components of the given
384  /// directed graph. In addition, the numbering of the components will
385  /// satisfy that there is no arc going from a higher numbered component
386  /// to a lower one (i.e. it provides a topological order of the components).
387  ///
388  /// The strongly connected components are the classes of an
389  /// equivalence relation on the nodes of a digraph. Two nodes are in
390  /// the same class if they are connected with directed paths in both
391  /// direction.
392  ///
393  /// \image html strongly_connected_components.png
394  /// \image latex strongly_connected_components.eps "Strongly connected components" width=\textwidth
395  ///
396  /// \param digraph The digraph.
397  /// \retval compMap A writable node map. The values will be set from 0 to
398  /// the number of the strongly connected components minus one. Each value
399  /// of the map will be set exactly once, and the values of a certain
400  /// component will be set continuously.
401  /// \return The number of strongly connected components.
402  /// \note By definition, the empty digraph has zero
403  /// strongly connected components.
404  ///
405  /// \see stronglyConnected(), countStronglyConnectedComponents()
406  template <typename Digraph, typename NodeMap>
407  int stronglyConnectedComponents(const Digraph& digraph, NodeMap& compMap) {
408    checkConcept<concepts::Digraph, Digraph>();
409    typedef typename Digraph::Node Node;
410    typedef typename Digraph::NodeIt NodeIt;
411    checkConcept<concepts::WriteMap<Node, int>, NodeMap>();
412
413    using namespace _connectivity_bits;
414
415    typedef std::vector<Node> Container;
416    typedef typename Container::iterator Iterator;
417
418    Container nodes(countNodes(digraph));
419    typedef LeaveOrderVisitor<Digraph, Iterator> Visitor;
420    Visitor visitor(nodes.begin());
421
422    DfsVisit<Digraph, Visitor> dfs(digraph, visitor);
423    dfs.init();
424    for (NodeIt it(digraph); it != INVALID; ++it) {
425      if (!dfs.reached(it)) {
426        dfs.addSource(it);
427        dfs.start();
428      }
429    }
430
431    typedef typename Container::reverse_iterator RIterator;
432    typedef ReverseDigraph<const Digraph> RDigraph;
433
434    RDigraph rdigraph(digraph);
435
436    int compNum = 0;
437
438    typedef FillMapVisitor<RDigraph, NodeMap> RVisitor;
439    RVisitor rvisitor(compMap, compNum);
440
441    DfsVisit<RDigraph, RVisitor> rdfs(rdigraph, rvisitor);
442
443    rdfs.init();
444    for (RIterator it = nodes.rbegin(); it != nodes.rend(); ++it) {
445      if (!rdfs.reached(*it)) {
446        rdfs.addSource(*it);
447        rdfs.start();
448        ++compNum;
449      }
450    }
451    return compNum;
452  }
453
454  /// \ingroup graph_properties
455  ///
456  /// \brief Find the cut arcs of the strongly connected components.
457  ///
458  /// This function finds the cut arcs of the strongly connected components
459  /// of the given digraph.
460  ///
461  /// The strongly connected components are the classes of an
462  /// equivalence relation on the nodes of a digraph. Two nodes are in
463  /// the same class if they are connected with directed paths in both
464  /// direction.
465  /// The strongly connected components are separated by the cut arcs.
466  ///
467  /// \param digraph The digraph.
468  /// \retval cutMap A writable arc map. The values will be set to \c true
469  /// for the cut arcs (exactly once for each cut arc), and will not be
470  /// changed for other arcs.
471  /// \return The number of cut arcs.
472  ///
473  /// \see stronglyConnected(), stronglyConnectedComponents()
474  template <typename Digraph, typename ArcMap>
475  int stronglyConnectedCutArcs(const Digraph& digraph, ArcMap& cutMap) {
476    checkConcept<concepts::Digraph, Digraph>();
477    typedef typename Digraph::Node Node;
478    typedef typename Digraph::Arc Arc;
479    typedef typename Digraph::NodeIt NodeIt;
480    checkConcept<concepts::WriteMap<Arc, bool>, ArcMap>();
481
482    using namespace _connectivity_bits;
483
484    typedef std::vector<Node> Container;
485    typedef typename Container::iterator Iterator;
486
487    Container nodes(countNodes(digraph));
488    typedef LeaveOrderVisitor<Digraph, Iterator> Visitor;
489    Visitor visitor(nodes.begin());
490
491    DfsVisit<Digraph, Visitor> dfs(digraph, visitor);
492    dfs.init();
493    for (NodeIt it(digraph); it != INVALID; ++it) {
494      if (!dfs.reached(it)) {
495        dfs.addSource(it);
496        dfs.start();
497      }
498    }
499
500    typedef typename Container::reverse_iterator RIterator;
501    typedef ReverseDigraph<const Digraph> RDigraph;
502
503    RDigraph rdigraph(digraph);
504
505    int cutNum = 0;
506
507    typedef StronglyConnectedCutArcsVisitor<RDigraph, ArcMap> RVisitor;
508    RVisitor rvisitor(rdigraph, cutMap, cutNum);
509
510    DfsVisit<RDigraph, RVisitor> rdfs(rdigraph, rvisitor);
511
512    rdfs.init();
513    for (RIterator it = nodes.rbegin(); it != nodes.rend(); ++it) {
514      if (!rdfs.reached(*it)) {
515        rdfs.addSource(*it);
516        rdfs.start();
517      }
518    }
519    return cutNum;
520  }
521
522  namespace _connectivity_bits {
523
524    template <typename Digraph>
525    class CountBiNodeConnectedComponentsVisitor : public DfsVisitor<Digraph> {
526    public:
527      typedef typename Digraph::Node Node;
528      typedef typename Digraph::Arc Arc;
529      typedef typename Digraph::Edge Edge;
530
531      CountBiNodeConnectedComponentsVisitor(const Digraph& graph, int &compNum)
532        : _graph(graph), _compNum(compNum),
533          _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
534
535      void start(const Node& node) {
536        _predMap.set(node, INVALID);
537      }
538
539      void reach(const Node& node) {
540        _numMap.set(node, _num);
541        _retMap.set(node, _num);
542        ++_num;
543      }
544
545      void discover(const Arc& edge) {
546        _predMap.set(_graph.target(edge), _graph.source(edge));
547      }
548
549      void examine(const Arc& edge) {
550        if (_graph.source(edge) == _graph.target(edge) &&
551            _graph.direction(edge)) {
552          ++_compNum;
553          return;
554        }
555        if (_predMap[_graph.source(edge)] == _graph.target(edge)) {
556          return;
557        }
558        if (_retMap[_graph.source(edge)] > _numMap[_graph.target(edge)]) {
559          _retMap.set(_graph.source(edge), _numMap[_graph.target(edge)]);
560        }
561      }
562
563      void backtrack(const Arc& edge) {
564        if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
565          _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
566        }
567        if (_numMap[_graph.source(edge)] <= _retMap[_graph.target(edge)]) {
568          ++_compNum;
569        }
570      }
571
572    private:
573      const Digraph& _graph;
574      int& _compNum;
575
576      typename Digraph::template NodeMap<int> _numMap;
577      typename Digraph::template NodeMap<int> _retMap;
578      typename Digraph::template NodeMap<Node> _predMap;
579      int _num;
580    };
581
582    template <typename Digraph, typename ArcMap>
583    class BiNodeConnectedComponentsVisitor : public DfsVisitor<Digraph> {
584    public:
585      typedef typename Digraph::Node Node;
586      typedef typename Digraph::Arc Arc;
587      typedef typename Digraph::Edge Edge;
588
589      BiNodeConnectedComponentsVisitor(const Digraph& graph,
590                                       ArcMap& compMap, int &compNum)
591        : _graph(graph), _compMap(compMap), _compNum(compNum),
592          _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
593
594      void start(const Node& node) {
595        _predMap.set(node, INVALID);
596      }
597
598      void reach(const Node& node) {
599        _numMap.set(node, _num);
600        _retMap.set(node, _num);
601        ++_num;
602      }
603
604      void discover(const Arc& edge) {
605        Node target = _graph.target(edge);
606        _predMap.set(target, edge);
607        _edgeStack.push(edge);
608      }
609
610      void examine(const Arc& edge) {
611        Node source = _graph.source(edge);
612        Node target = _graph.target(edge);
613        if (source == target && _graph.direction(edge)) {
614          _compMap.set(edge, _compNum);
615          ++_compNum;
616          return;
617        }
618        if (_numMap[target] < _numMap[source]) {
619          if (_predMap[source] != _graph.oppositeArc(edge)) {
620            _edgeStack.push(edge);
621          }
622        }
623        if (_predMap[source] != INVALID &&
624            target == _graph.source(_predMap[source])) {
625          return;
626        }
627        if (_retMap[source] > _numMap[target]) {
628          _retMap.set(source, _numMap[target]);
629        }
630      }
631
632      void backtrack(const Arc& edge) {
633        Node source = _graph.source(edge);
634        Node target = _graph.target(edge);
635        if (_retMap[source] > _retMap[target]) {
636          _retMap.set(source, _retMap[target]);
637        }
638        if (_numMap[source] <= _retMap[target]) {
639          while (_edgeStack.top() != edge) {
640            _compMap.set(_edgeStack.top(), _compNum);
641            _edgeStack.pop();
642          }
643          _compMap.set(edge, _compNum);
644          _edgeStack.pop();
645          ++_compNum;
646        }
647      }
648
649    private:
650      const Digraph& _graph;
651      ArcMap& _compMap;
652      int& _compNum;
653
654      typename Digraph::template NodeMap<int> _numMap;
655      typename Digraph::template NodeMap<int> _retMap;
656      typename Digraph::template NodeMap<Arc> _predMap;
657      std::stack<Edge> _edgeStack;
658      int _num;
659    };
660
661
662    template <typename Digraph, typename NodeMap>
663    class BiNodeConnectedCutNodesVisitor : public DfsVisitor<Digraph> {
664    public:
665      typedef typename Digraph::Node Node;
666      typedef typename Digraph::Arc Arc;
667      typedef typename Digraph::Edge Edge;
668
669      BiNodeConnectedCutNodesVisitor(const Digraph& graph, NodeMap& cutMap,
670                                     int& cutNum)
671        : _graph(graph), _cutMap(cutMap), _cutNum(cutNum),
672          _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
673
674      void start(const Node& node) {
675        _predMap.set(node, INVALID);
676        rootCut = false;
677      }
678
679      void reach(const Node& node) {
680        _numMap.set(node, _num);
681        _retMap.set(node, _num);
682        ++_num;
683      }
684
685      void discover(const Arc& edge) {
686        _predMap.set(_graph.target(edge), _graph.source(edge));
687      }
688
689      void examine(const Arc& edge) {
690        if (_graph.source(edge) == _graph.target(edge) &&
691            _graph.direction(edge)) {
692          if (!_cutMap[_graph.source(edge)]) {
693            _cutMap.set(_graph.source(edge), true);
694            ++_cutNum;
695          }
696          return;
697        }
698        if (_predMap[_graph.source(edge)] == _graph.target(edge)) return;
699        if (_retMap[_graph.source(edge)] > _numMap[_graph.target(edge)]) {
700          _retMap.set(_graph.source(edge), _numMap[_graph.target(edge)]);
701        }
702      }
703
704      void backtrack(const Arc& edge) {
705        if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
706          _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
707        }
708        if (_numMap[_graph.source(edge)] <= _retMap[_graph.target(edge)]) {
709          if (_predMap[_graph.source(edge)] != INVALID) {
710            if (!_cutMap[_graph.source(edge)]) {
711              _cutMap.set(_graph.source(edge), true);
712              ++_cutNum;
713            }
714          } else if (rootCut) {
715            if (!_cutMap[_graph.source(edge)]) {
716              _cutMap.set(_graph.source(edge), true);
717              ++_cutNum;
718            }
719          } else {
720            rootCut = true;
721          }
722        }
723      }
724
725    private:
726      const Digraph& _graph;
727      NodeMap& _cutMap;
728      int& _cutNum;
729
730      typename Digraph::template NodeMap<int> _numMap;
731      typename Digraph::template NodeMap<int> _retMap;
732      typename Digraph::template NodeMap<Node> _predMap;
733      std::stack<Edge> _edgeStack;
734      int _num;
735      bool rootCut;
736    };
737
738  }
739
740  template <typename Graph>
741  int countBiNodeConnectedComponents(const Graph& graph);
742
743  /// \ingroup graph_properties
744  ///
745  /// \brief Check whether an undirected graph is bi-node-connected.
746  ///
747  /// This function checks whether the given undirected graph is
748  /// bi-node-connected, i.e. a connected graph without articulation
749  /// node.
750  ///
751  /// \return \c true if the graph bi-node-connected.
752  /// \note By definition, the empty graph is bi-node-connected.
753  ///
754  /// \see countBiNodeConnectedComponents(), biNodeConnectedComponents()
755  template <typename Graph>
756  bool biNodeConnected(const Graph& graph) {
757    bool hasNonIsolated = false, hasIsolated = false;
758    for (typename Graph::NodeIt n(graph); n != INVALID; ++n) {
759      if (typename Graph::OutArcIt(graph, n) == INVALID) {
760        if (hasIsolated || hasNonIsolated) {
761          return false;
762        } else {
763          hasIsolated = true;
764        }
765      } else {
766        if (hasIsolated) {
767          return false;
768        } else {
769          hasNonIsolated = true;
770        }
771      }
772    }
773    return countBiNodeConnectedComponents(graph) <= 1;
774  }
775
776  /// \ingroup graph_properties
777  ///
778  /// \brief Count the number of bi-node-connected components of an
779  /// undirected graph.
780  ///
781  /// This function counts the number of bi-node-connected components of
782  /// the given undirected graph.
783  ///
784  /// The bi-node-connected components are the classes of an equivalence
785  /// relation on the edges of a undirected graph. Two edges are in the
786  /// same class if they are on same circle.
787  ///
788  /// \return The number of bi-node-connected components.
789  ///
790  /// \see biNodeConnected(), biNodeConnectedComponents()
791  template <typename Graph>
792  int countBiNodeConnectedComponents(const Graph& graph) {
793    checkConcept<concepts::Graph, Graph>();
794    typedef typename Graph::NodeIt NodeIt;
795
796    using namespace _connectivity_bits;
797
798    typedef CountBiNodeConnectedComponentsVisitor<Graph> Visitor;
799
800    int compNum = 0;
801    Visitor visitor(graph, compNum);
802
803    DfsVisit<Graph, Visitor> dfs(graph, visitor);
804    dfs.init();
805
806    for (NodeIt it(graph); it != INVALID; ++it) {
807      if (!dfs.reached(it)) {
808        dfs.addSource(it);
809        dfs.start();
810      }
811    }
812    return compNum;
813  }
814
815  /// \ingroup graph_properties
816  ///
817  /// \brief Find the bi-node-connected components of an undirected graph.
818  ///
819  /// This function finds the bi-node-connected components of the given
820  /// undirected graph.
821  ///
822  /// The bi-node-connected components are the classes of an equivalence
823  /// relation on the edges of a undirected graph. Two edges are in the
824  /// same class if they are on same circle.
825  ///
826  /// \image html node_biconnected_components.png
827  /// \image latex node_biconnected_components.eps "bi-node-connected components" width=\textwidth
828  ///
829  /// \param graph The undirected graph.
830  /// \retval compMap A writable edge map. The values will be set from 0
831  /// to the number of the bi-node-connected components minus one. Each
832  /// value of the map will be set exactly once, and the values of a
833  /// certain component will be set continuously.
834  /// \return The number of bi-node-connected components.
835  ///
836  /// \see biNodeConnected(), countBiNodeConnectedComponents()
837  template <typename Graph, typename EdgeMap>
838  int biNodeConnectedComponents(const Graph& graph,
839                                EdgeMap& compMap) {
840    checkConcept<concepts::Graph, Graph>();
841    typedef typename Graph::NodeIt NodeIt;
842    typedef typename Graph::Edge Edge;
843    checkConcept<concepts::WriteMap<Edge, int>, EdgeMap>();
844
845    using namespace _connectivity_bits;
846
847    typedef BiNodeConnectedComponentsVisitor<Graph, EdgeMap> Visitor;
848
849    int compNum = 0;
850    Visitor visitor(graph, compMap, compNum);
851
852    DfsVisit<Graph, Visitor> dfs(graph, visitor);
853    dfs.init();
854
855    for (NodeIt it(graph); it != INVALID; ++it) {
856      if (!dfs.reached(it)) {
857        dfs.addSource(it);
858        dfs.start();
859      }
860    }
861    return compNum;
862  }
863
864  /// \ingroup graph_properties
865  ///
866  /// \brief Find the bi-node-connected cut nodes in an undirected graph.
867  ///
868  /// This function finds the bi-node-connected cut nodes in the given
869  /// undirected graph.
870  ///
871  /// The bi-node-connected components are the classes of an equivalence
872  /// relation on the edges of a undirected graph. Two edges are in the
873  /// same class if they are on same circle.
874  /// The bi-node-connected components are separted by the cut nodes of
875  /// the components.
876  ///
877  /// \param graph The undirected graph.
878  /// \retval cutMap A writable node map. The values will be set to
879  /// \c true for the nodes that separate two or more components
880  /// (exactly once for each cut node), and will not be changed for
881  /// other nodes.
882  /// \return The number of the cut nodes.
883  ///
884  /// \see biNodeConnected(), biNodeConnectedComponents()
885  template <typename Graph, typename NodeMap>
886  int biNodeConnectedCutNodes(const Graph& graph, NodeMap& cutMap) {
887    checkConcept<concepts::Graph, Graph>();
888    typedef typename Graph::Node Node;
889    typedef typename Graph::NodeIt NodeIt;
890    checkConcept<concepts::WriteMap<Node, bool>, NodeMap>();
891
892    using namespace _connectivity_bits;
893
894    typedef BiNodeConnectedCutNodesVisitor<Graph, NodeMap> Visitor;
895
896    int cutNum = 0;
897    Visitor visitor(graph, cutMap, cutNum);
898
899    DfsVisit<Graph, Visitor> dfs(graph, visitor);
900    dfs.init();
901
902    for (NodeIt it(graph); it != INVALID; ++it) {
903      if (!dfs.reached(it)) {
904        dfs.addSource(it);
905        dfs.start();
906      }
907    }
908    return cutNum;
909  }
910
911  namespace _connectivity_bits {
912
913    template <typename Digraph>
914    class CountBiEdgeConnectedComponentsVisitor : public DfsVisitor<Digraph> {
915    public:
916      typedef typename Digraph::Node Node;
917      typedef typename Digraph::Arc Arc;
918      typedef typename Digraph::Edge Edge;
919
920      CountBiEdgeConnectedComponentsVisitor(const Digraph& graph, int &compNum)
921        : _graph(graph), _compNum(compNum),
922          _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
923
924      void start(const Node& node) {
925        _predMap.set(node, INVALID);
926      }
927
928      void reach(const Node& node) {
929        _numMap.set(node, _num);
930        _retMap.set(node, _num);
931        ++_num;
932      }
933
934      void leave(const Node& node) {
935        if (_numMap[node] <= _retMap[node]) {
936          ++_compNum;
937        }
938      }
939
940      void discover(const Arc& edge) {
941        _predMap.set(_graph.target(edge), edge);
942      }
943
944      void examine(const Arc& edge) {
945        if (_predMap[_graph.source(edge)] == _graph.oppositeArc(edge)) {
946          return;
947        }
948        if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
949          _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
950        }
951      }
952
953      void backtrack(const Arc& edge) {
954        if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
955          _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
956        }
957      }
958
959    private:
960      const Digraph& _graph;
961      int& _compNum;
962
963      typename Digraph::template NodeMap<int> _numMap;
964      typename Digraph::template NodeMap<int> _retMap;
965      typename Digraph::template NodeMap<Arc> _predMap;
966      int _num;
967    };
968
969    template <typename Digraph, typename NodeMap>
970    class BiEdgeConnectedComponentsVisitor : public DfsVisitor<Digraph> {
971    public:
972      typedef typename Digraph::Node Node;
973      typedef typename Digraph::Arc Arc;
974      typedef typename Digraph::Edge Edge;
975
976      BiEdgeConnectedComponentsVisitor(const Digraph& graph,
977                                       NodeMap& compMap, int &compNum)
978        : _graph(graph), _compMap(compMap), _compNum(compNum),
979          _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
980
981      void start(const Node& node) {
982        _predMap.set(node, INVALID);
983      }
984
985      void reach(const Node& node) {
986        _numMap.set(node, _num);
987        _retMap.set(node, _num);
988        _nodeStack.push(node);
989        ++_num;
990      }
991
992      void leave(const Node& node) {
993        if (_numMap[node] <= _retMap[node]) {
994          while (_nodeStack.top() != node) {
995            _compMap.set(_nodeStack.top(), _compNum);
996            _nodeStack.pop();
997          }
998          _compMap.set(node, _compNum);
999          _nodeStack.pop();
1000          ++_compNum;
1001        }
1002      }
1003
1004      void discover(const Arc& edge) {
1005        _predMap.set(_graph.target(edge), edge);
1006      }
1007
1008      void examine(const Arc& edge) {
1009        if (_predMap[_graph.source(edge)] == _graph.oppositeArc(edge)) {
1010          return;
1011        }
1012        if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
1013          _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
1014        }
1015      }
1016
1017      void backtrack(const Arc& edge) {
1018        if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
1019          _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
1020        }
1021      }
1022
1023    private:
1024      const Digraph& _graph;
1025      NodeMap& _compMap;
1026      int& _compNum;
1027
1028      typename Digraph::template NodeMap<int> _numMap;
1029      typename Digraph::template NodeMap<int> _retMap;
1030      typename Digraph::template NodeMap<Arc> _predMap;
1031      std::stack<Node> _nodeStack;
1032      int _num;
1033    };
1034
1035
1036    template <typename Digraph, typename ArcMap>
1037    class BiEdgeConnectedCutEdgesVisitor : public DfsVisitor<Digraph> {
1038    public:
1039      typedef typename Digraph::Node Node;
1040      typedef typename Digraph::Arc Arc;
1041      typedef typename Digraph::Edge Edge;
1042
1043      BiEdgeConnectedCutEdgesVisitor(const Digraph& graph,
1044                                     ArcMap& cutMap, int &cutNum)
1045        : _graph(graph), _cutMap(cutMap), _cutNum(cutNum),
1046          _numMap(graph), _retMap(graph), _predMap(graph), _num(0) {}
1047
1048      void start(const Node& node) {
1049        _predMap[node] = INVALID;
1050      }
1051
1052      void reach(const Node& node) {
1053        _numMap.set(node, _num);
1054        _retMap.set(node, _num);
1055        ++_num;
1056      }
1057
1058      void leave(const Node& node) {
1059        if (_numMap[node] <= _retMap[node]) {
1060          if (_predMap[node] != INVALID) {
1061            _cutMap.set(_predMap[node], true);
1062            ++_cutNum;
1063          }
1064        }
1065      }
1066
1067      void discover(const Arc& edge) {
1068        _predMap.set(_graph.target(edge), edge);
1069      }
1070
1071      void examine(const Arc& edge) {
1072        if (_predMap[_graph.source(edge)] == _graph.oppositeArc(edge)) {
1073          return;
1074        }
1075        if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
1076          _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
1077        }
1078      }
1079
1080      void backtrack(const Arc& edge) {
1081        if (_retMap[_graph.source(edge)] > _retMap[_graph.target(edge)]) {
1082          _retMap.set(_graph.source(edge), _retMap[_graph.target(edge)]);
1083        }
1084      }
1085
1086    private:
1087      const Digraph& _graph;
1088      ArcMap& _cutMap;
1089      int& _cutNum;
1090
1091      typename Digraph::template NodeMap<int> _numMap;
1092      typename Digraph::template NodeMap<int> _retMap;
1093      typename Digraph::template NodeMap<Arc> _predMap;
1094      int _num;
1095    };
1096  }
1097
1098  template <typename Graph>
1099  int countBiEdgeConnectedComponents(const Graph& graph);
1100
1101  /// \ingroup graph_properties
1102  ///
1103  /// \brief Check whether an undirected graph is bi-edge-connected.
1104  ///
1105  /// This function checks whether the given undirected graph is
1106  /// bi-edge-connected, i.e. any two nodes are connected with at least
1107  /// two edge-disjoint paths.
1108  ///
1109  /// \return \c true if the graph is bi-edge-connected.
1110  /// \note By definition, the empty graph is bi-edge-connected.
1111  ///
1112  /// \see countBiEdgeConnectedComponents(), biEdgeConnectedComponents()
1113  template <typename Graph>
1114  bool biEdgeConnected(const Graph& graph) {
1115    return countBiEdgeConnectedComponents(graph) <= 1;
1116  }
1117
1118  /// \ingroup graph_properties
1119  ///
1120  /// \brief Count the number of bi-edge-connected components of an
1121  /// undirected graph.
1122  ///
1123  /// This function counts the number of bi-edge-connected components of
1124  /// the given undirected graph.
1125  ///
1126  /// The bi-edge-connected components are the classes of an equivalence
1127  /// relation on the nodes of an undirected graph. Two nodes are in the
1128  /// same class if they are connected with at least two edge-disjoint
1129  /// paths.
1130  ///
1131  /// \return The number of bi-edge-connected components.
1132  ///
1133  /// \see biEdgeConnected(), biEdgeConnectedComponents()
1134  template <typename Graph>
1135  int countBiEdgeConnectedComponents(const Graph& graph) {
1136    checkConcept<concepts::Graph, Graph>();
1137    typedef typename Graph::NodeIt NodeIt;
1138
1139    using namespace _connectivity_bits;
1140
1141    typedef CountBiEdgeConnectedComponentsVisitor<Graph> Visitor;
1142
1143    int compNum = 0;
1144    Visitor visitor(graph, compNum);
1145
1146    DfsVisit<Graph, Visitor> dfs(graph, visitor);
1147    dfs.init();
1148
1149    for (NodeIt it(graph); it != INVALID; ++it) {
1150      if (!dfs.reached(it)) {
1151        dfs.addSource(it);
1152        dfs.start();
1153      }
1154    }
1155    return compNum;
1156  }
1157
1158  /// \ingroup graph_properties
1159  ///
1160  /// \brief Find the bi-edge-connected components of an undirected graph.
1161  ///
1162  /// This function finds the bi-edge-connected components of the given
1163  /// undirected graph.
1164  ///
1165  /// The bi-edge-connected components are the classes of an equivalence
1166  /// relation on the nodes of an undirected graph. Two nodes are in the
1167  /// same class if they are connected with at least two edge-disjoint
1168  /// paths.
1169  ///
1170  /// \image html edge_biconnected_components.png
1171  /// \image latex edge_biconnected_components.eps "bi-edge-connected components" width=\textwidth
1172  ///
1173  /// \param graph The undirected graph.
1174  /// \retval compMap A writable node map. The values will be set from 0 to
1175  /// the number of the bi-edge-connected components minus one. Each value
1176  /// of the map will be set exactly once, and the values of a certain
1177  /// component will be set continuously.
1178  /// \return The number of bi-edge-connected components.
1179  ///
1180  /// \see biEdgeConnected(), countBiEdgeConnectedComponents()
1181  template <typename Graph, typename NodeMap>
1182  int biEdgeConnectedComponents(const Graph& graph, NodeMap& compMap) {
1183    checkConcept<concepts::Graph, Graph>();
1184    typedef typename Graph::NodeIt NodeIt;
1185    typedef typename Graph::Node Node;
1186    checkConcept<concepts::WriteMap<Node, int>, NodeMap>();
1187
1188    using namespace _connectivity_bits;
1189
1190    typedef BiEdgeConnectedComponentsVisitor<Graph, NodeMap> Visitor;
1191
1192    int compNum = 0;
1193    Visitor visitor(graph, compMap, compNum);
1194
1195    DfsVisit<Graph, Visitor> dfs(graph, visitor);
1196    dfs.init();
1197
1198    for (NodeIt it(graph); it != INVALID; ++it) {
1199      if (!dfs.reached(it)) {
1200        dfs.addSource(it);
1201        dfs.start();
1202      }
1203    }
1204    return compNum;
1205  }
1206
1207  /// \ingroup graph_properties
1208  ///
1209  /// \brief Find the bi-edge-connected cut edges in an undirected graph.
1210  ///
1211  /// This function finds the bi-edge-connected cut edges in the given
1212  /// undirected graph.
1213  ///
1214  /// The bi-edge-connected components are the classes of an equivalence
1215  /// relation on the nodes of an undirected graph. Two nodes are in the
1216  /// same class if they are connected with at least two edge-disjoint
1217  /// paths.
1218  /// The bi-edge-connected components are separted by the cut edges of
1219  /// the components.
1220  ///
1221  /// \param graph The undirected graph.
1222  /// \retval cutMap A writable edge map. The values will be set to \c true
1223  /// for the cut edges (exactly once for each cut edge), and will not be
1224  /// changed for other edges.
1225  /// \return The number of cut edges.
1226  ///
1227  /// \see biEdgeConnected(), biEdgeConnectedComponents()
1228  template <typename Graph, typename EdgeMap>
1229  int biEdgeConnectedCutEdges(const Graph& graph, EdgeMap& cutMap) {
1230    checkConcept<concepts::Graph, Graph>();
1231    typedef typename Graph::NodeIt NodeIt;
1232    typedef typename Graph::Edge Edge;
1233    checkConcept<concepts::WriteMap<Edge, bool>, EdgeMap>();
1234
1235    using namespace _connectivity_bits;
1236
1237    typedef BiEdgeConnectedCutEdgesVisitor<Graph, EdgeMap> Visitor;
1238
1239    int cutNum = 0;
1240    Visitor visitor(graph, cutMap, cutNum);
1241
1242    DfsVisit<Graph, Visitor> dfs(graph, visitor);
1243    dfs.init();
1244
1245    for (NodeIt it(graph); it != INVALID; ++it) {
1246      if (!dfs.reached(it)) {
1247        dfs.addSource(it);
1248        dfs.start();
1249      }
1250    }
1251    return cutNum;
1252  }
1253
1254
1255  namespace _connectivity_bits {
1256
1257    template <typename Digraph, typename IntNodeMap>
1258    class TopologicalSortVisitor : public DfsVisitor<Digraph> {
1259    public:
1260      typedef typename Digraph::Node Node;
1261      typedef typename Digraph::Arc edge;
1262
1263      TopologicalSortVisitor(IntNodeMap& order, int num)
1264        : _order(order), _num(num) {}
1265
1266      void leave(const Node& node) {
1267        _order.set(node, --_num);
1268      }
1269
1270    private:
1271      IntNodeMap& _order;
1272      int _num;
1273    };
1274
1275  }
1276
1277  /// \ingroup graph_properties
1278  ///
1279  /// \brief Check whether a digraph is DAG.
1280  ///
1281  /// This function checks whether the given digraph is DAG, i.e.
1282  /// \e Directed \e Acyclic \e Graph.
1283  /// \return \c true if there is no directed cycle in the digraph.
1284  /// \see acyclic()
1285  template <typename Digraph>
1286  bool dag(const Digraph& digraph) {
1287
1288    checkConcept<concepts::Digraph, Digraph>();
1289
1290    typedef typename Digraph::Node Node;
1291    typedef typename Digraph::NodeIt NodeIt;
1292    typedef typename Digraph::Arc Arc;
1293
1294    typedef typename Digraph::template NodeMap<bool> ProcessedMap;
1295
1296    typename Dfs<Digraph>::template SetProcessedMap<ProcessedMap>::
1297      Create dfs(digraph);
1298
1299    ProcessedMap processed(digraph);
1300    dfs.processedMap(processed);
1301
1302    dfs.init();
1303    for (NodeIt it(digraph); it != INVALID; ++it) {
1304      if (!dfs.reached(it)) {
1305        dfs.addSource(it);
1306        while (!dfs.emptyQueue()) {
1307          Arc arc = dfs.nextArc();
1308          Node target = digraph.target(arc);
1309          if (dfs.reached(target) && !processed[target]) {
1310            return false;
1311          }
1312          dfs.processNextArc();
1313        }
1314      }
1315    }
1316    return true;
1317  }
1318
1319  /// \ingroup graph_properties
1320  ///
1321  /// \brief Sort the nodes of a DAG into topolgical order.
1322  ///
1323  /// This function sorts the nodes of the given acyclic digraph (DAG)
1324  /// into topolgical order.
1325  ///
1326  /// \param digraph The digraph, which must be DAG.
1327  /// \retval order A writable node map. The values will be set from 0 to
1328  /// the number of the nodes in the digraph minus one. Each value of the
1329  /// map will be set exactly once, and the values will be set descending
1330  /// order.
1331  ///
1332  /// \see dag(), checkedTopologicalSort()
1333  template <typename Digraph, typename NodeMap>
1334  void topologicalSort(const Digraph& digraph, NodeMap& order) {
1335    using namespace _connectivity_bits;
1336
1337    checkConcept<concepts::Digraph, Digraph>();
1338    checkConcept<concepts::WriteMap<typename Digraph::Node, int>, NodeMap>();
1339
1340    typedef typename Digraph::Node Node;
1341    typedef typename Digraph::NodeIt NodeIt;
1342    typedef typename Digraph::Arc Arc;
1343
1344    TopologicalSortVisitor<Digraph, NodeMap>
1345      visitor(order, countNodes(digraph));
1346
1347    DfsVisit<Digraph, TopologicalSortVisitor<Digraph, NodeMap> >
1348      dfs(digraph, visitor);
1349
1350    dfs.init();
1351    for (NodeIt it(digraph); it != INVALID; ++it) {
1352      if (!dfs.reached(it)) {
1353        dfs.addSource(it);
1354        dfs.start();
1355      }
1356    }
1357  }
1358
1359  /// \ingroup graph_properties
1360  ///
1361  /// \brief Sort the nodes of a DAG into topolgical order.
1362  ///
1363  /// This function sorts the nodes of the given acyclic digraph (DAG)
1364  /// into topolgical order and also checks whether the given digraph
1365  /// is DAG.
1366  ///
1367  /// \param digraph The digraph.
1368  /// \retval order A readable and writable node map. The values will be
1369  /// set from 0 to the number of the nodes in the digraph minus one.
1370  /// Each value of the map will be set exactly once, and the values will
1371  /// be set descending order.
1372  /// \return \c false if the digraph is not DAG.
1373  ///
1374  /// \see dag(), topologicalSort()
1375  template <typename Digraph, typename NodeMap>
1376  bool checkedTopologicalSort(const Digraph& digraph, NodeMap& order) {
1377    using namespace _connectivity_bits;
1378
1379    checkConcept<concepts::Digraph, Digraph>();
1380    checkConcept<concepts::ReadWriteMap<typename Digraph::Node, int>,
1381      NodeMap>();
1382
1383    typedef typename Digraph::Node Node;
1384    typedef typename Digraph::NodeIt NodeIt;
1385    typedef typename Digraph::Arc Arc;
1386
1387    for (NodeIt it(digraph); it != INVALID; ++it) {
1388      order.set(it, -1);
1389    }
1390
1391    TopologicalSortVisitor<Digraph, NodeMap>
1392      visitor(order, countNodes(digraph));
1393
1394    DfsVisit<Digraph, TopologicalSortVisitor<Digraph, NodeMap> >
1395      dfs(digraph, visitor);
1396
1397    dfs.init();
1398    for (NodeIt it(digraph); it != INVALID; ++it) {
1399      if (!dfs.reached(it)) {
1400        dfs.addSource(it);
1401        while (!dfs.emptyQueue()) {
1402           Arc arc = dfs.nextArc();
1403           Node target = digraph.target(arc);
1404           if (dfs.reached(target) && order[target] == -1) {
1405             return false;
1406           }
1407           dfs.processNextArc();
1408         }
1409      }
1410    }
1411    return true;
1412  }
1413
1414  /// \ingroup graph_properties
1415  ///
1416  /// \brief Check whether an undirected graph is acyclic.
1417  ///
1418  /// This function checks whether the given undirected graph is acyclic.
1419  /// \return \c true if there is no cycle in the graph.
1420  /// \see dag()
1421  template <typename Graph>
1422  bool acyclic(const Graph& graph) {
1423    checkConcept<concepts::Graph, Graph>();
1424    typedef typename Graph::Node Node;
1425    typedef typename Graph::NodeIt NodeIt;
1426    typedef typename Graph::Arc Arc;
1427    Dfs<Graph> dfs(graph);
1428    dfs.init();
1429    for (NodeIt it(graph); it != INVALID; ++it) {
1430      if (!dfs.reached(it)) {
1431        dfs.addSource(it);
1432        while (!dfs.emptyQueue()) {
1433          Arc arc = dfs.nextArc();
1434          Node source = graph.source(arc);
1435          Node target = graph.target(arc);
1436          if (dfs.reached(target) &&
1437              dfs.predArc(source) != graph.oppositeArc(arc)) {
1438            return false;
1439          }
1440          dfs.processNextArc();
1441        }
1442      }
1443    }
1444    return true;
1445  }
1446
1447  /// \ingroup graph_properties
1448  ///
1449  /// \brief Check whether an undirected graph is tree.
1450  ///
1451  /// This function checks whether the given undirected graph is tree.
1452  /// \return \c true if the graph is acyclic and connected.
1453  /// \see acyclic(), connected()
1454  template <typename Graph>
1455  bool tree(const Graph& graph) {
1456    checkConcept<concepts::Graph, Graph>();
1457    typedef typename Graph::Node Node;
1458    typedef typename Graph::NodeIt NodeIt;
1459    typedef typename Graph::Arc Arc;
1460    if (NodeIt(graph) == INVALID) return true;
1461    Dfs<Graph> dfs(graph);
1462    dfs.init();
1463    dfs.addSource(NodeIt(graph));
1464    while (!dfs.emptyQueue()) {
1465      Arc arc = dfs.nextArc();
1466      Node source = graph.source(arc);
1467      Node target = graph.target(arc);
1468      if (dfs.reached(target) &&
1469          dfs.predArc(source) != graph.oppositeArc(arc)) {
1470        return false;
1471      }
1472      dfs.processNextArc();
1473    }
1474    for (NodeIt it(graph); it != INVALID; ++it) {
1475      if (!dfs.reached(it)) {
1476        return false;
1477      }
1478    }
1479    return true;
1480  }
1481
1482  namespace _connectivity_bits {
1483
1484    template <typename Digraph>
1485    class BipartiteVisitor : public BfsVisitor<Digraph> {
1486    public:
1487      typedef typename Digraph::Arc Arc;
1488      typedef typename Digraph::Node Node;
1489
1490      BipartiteVisitor(const Digraph& graph, bool& bipartite)
1491        : _graph(graph), _part(graph), _bipartite(bipartite) {}
1492
1493      void start(const Node& node) {
1494        _part[node] = true;
1495      }
1496      void discover(const Arc& edge) {
1497        _part.set(_graph.target(edge), !_part[_graph.source(edge)]);
1498      }
1499      void examine(const Arc& edge) {
1500        _bipartite = _bipartite &&
1501          _part[_graph.target(edge)] != _part[_graph.source(edge)];
1502      }
1503
1504    private:
1505
1506      const Digraph& _graph;
1507      typename Digraph::template NodeMap<bool> _part;
1508      bool& _bipartite;
1509    };
1510
1511    template <typename Digraph, typename PartMap>
1512    class BipartitePartitionsVisitor : public BfsVisitor<Digraph> {
1513    public:
1514      typedef typename Digraph::Arc Arc;
1515      typedef typename Digraph::Node Node;
1516
1517      BipartitePartitionsVisitor(const Digraph& graph,
1518                                 PartMap& part, bool& bipartite)
1519        : _graph(graph), _part(part), _bipartite(bipartite) {}
1520
1521      void start(const Node& node) {
1522        _part.set(node, true);
1523      }
1524      void discover(const Arc& edge) {
1525        _part.set(_graph.target(edge), !_part[_graph.source(edge)]);
1526      }
1527      void examine(const Arc& edge) {
1528        _bipartite = _bipartite &&
1529          _part[_graph.target(edge)] != _part[_graph.source(edge)];
1530      }
1531
1532    private:
1533
1534      const Digraph& _graph;
1535      PartMap& _part;
1536      bool& _bipartite;
1537    };
1538  }
1539
1540  /// \ingroup graph_properties
1541  ///
1542  /// \brief Check whether an undirected graph is bipartite.
1543  ///
1544  /// The function checks whether the given undirected graph is bipartite.
1545  /// \return \c true if the graph is bipartite.
1546  ///
1547  /// \see bipartitePartitions()
1548  template<typename Graph>
1549  bool bipartite(const Graph &graph){
1550    using namespace _connectivity_bits;
1551
1552    checkConcept<concepts::Graph, Graph>();
1553
1554    typedef typename Graph::NodeIt NodeIt;
1555    typedef typename Graph::ArcIt ArcIt;
1556
1557    bool bipartite = true;
1558
1559    BipartiteVisitor<Graph>
1560      visitor(graph, bipartite);
1561    BfsVisit<Graph, BipartiteVisitor<Graph> >
1562      bfs(graph, visitor);
1563    bfs.init();
1564    for(NodeIt it(graph); it != INVALID; ++it) {
1565      if(!bfs.reached(it)){
1566        bfs.addSource(it);
1567        while (!bfs.emptyQueue()) {
1568          bfs.processNextNode();
1569          if (!bipartite) return false;
1570        }
1571      }
1572    }
1573    return true;
1574  }
1575
1576  /// \ingroup graph_properties
1577  ///
1578  /// \brief Find the bipartite partitions of an undirected graph.
1579  ///
1580  /// This function checks whether the given undirected graph is bipartite
1581  /// and gives back the bipartite partitions.
1582  ///
1583  /// \image html bipartite_partitions.png
1584  /// \image latex bipartite_partitions.eps "Bipartite partititions" width=\textwidth
1585  ///
1586  /// \param graph The undirected graph.
1587  /// \retval partMap A writable node map of \c bool (or convertible) value
1588  /// type. The values will be set to \c true for one component and
1589  /// \c false for the other one.
1590  /// \return \c true if the graph is bipartite, \c false otherwise.
1591  ///
1592  /// \see bipartite()
1593  template<typename Graph, typename NodeMap>
1594  bool bipartitePartitions(const Graph &graph, NodeMap &partMap){
1595    using namespace _connectivity_bits;
1596
1597    checkConcept<concepts::Graph, Graph>();
1598    checkConcept<concepts::WriteMap<typename Graph::Node, bool>, NodeMap>();
1599
1600    typedef typename Graph::Node Node;
1601    typedef typename Graph::NodeIt NodeIt;
1602    typedef typename Graph::ArcIt ArcIt;
1603
1604    bool bipartite = true;
1605
1606    BipartitePartitionsVisitor<Graph, NodeMap>
1607      visitor(graph, partMap, bipartite);
1608    BfsVisit<Graph, BipartitePartitionsVisitor<Graph, NodeMap> >
1609      bfs(graph, visitor);
1610    bfs.init();
1611    for(NodeIt it(graph); it != INVALID; ++it) {
1612      if(!bfs.reached(it)){
1613        bfs.addSource(it);
1614        while (!bfs.emptyQueue()) {
1615          bfs.processNextNode();
1616          if (!bipartite) return false;
1617        }
1618      }
1619    }
1620    return true;
1621  }
1622
1623  /// \ingroup graph_properties
1624  ///
1625  /// \brief Check whether the given graph contains no loop arcs/edges.
1626  ///
1627  /// This function returns \c true if there are no loop arcs/edges in
1628  /// the given graph. It works for both directed and undirected graphs.
1629  template <typename Graph>
1630  bool loopFree(const Graph& graph) {
1631    for (typename Graph::ArcIt it(graph); it != INVALID; ++it) {
1632      if (graph.source(it) == graph.target(it)) return false;
1633    }
1634    return true;
1635  }
1636
1637  /// \ingroup graph_properties
1638  ///
1639  /// \brief Check whether the given graph contains no parallel arcs/edges.
1640  ///
1641  /// This function returns \c true if there are no parallel arcs/edges in
1642  /// the given graph. It works for both directed and undirected graphs.
1643  template <typename Graph>
1644  bool parallelFree(const Graph& graph) {
1645    typename Graph::template NodeMap<int> reached(graph, 0);
1646    int cnt = 1;
1647    for (typename Graph::NodeIt n(graph); n != INVALID; ++n) {
1648      for (typename Graph::OutArcIt a(graph, n); a != INVALID; ++a) {
1649        if (reached[graph.target(a)] == cnt) return false;
1650        reached[graph.target(a)] = cnt;
1651      }
1652      ++cnt;
1653    }
1654    return true;
1655  }
1656
1657  /// \ingroup graph_properties
1658  ///
1659  /// \brief Check whether the given graph is simple.
1660  ///
1661  /// This function returns \c true if the given graph is simple, i.e.
1662  /// it contains no loop arcs/edges and no parallel arcs/edges.
1663  /// The function works for both directed and undirected graphs.
1664  /// \see loopFree(), parallelFree()
1665  template <typename Graph>
1666  bool simpleGraph(const Graph& graph) {
1667    typename Graph::template NodeMap<int> reached(graph, 0);
1668    int cnt = 1;
1669    for (typename Graph::NodeIt n(graph); n != INVALID; ++n) {
1670      reached[n] = cnt;
1671      for (typename Graph::OutArcIt a(graph, n); a != INVALID; ++a) {
1672        if (reached[graph.target(a)] == cnt) return false;
1673        reached[graph.target(a)] = cnt;
1674      }
1675      ++cnt;
1676    }
1677    return true;
1678  }
1679
1680} //namespace lemon
1681
1682#endif //LEMON_CONNECTIVITY_H
Note: See TracBrowser for help on using the repository browser.