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