cmComputeComponentGraph.h 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #pragma once
  4. #include "cmConfigure.h" // IWYU pragma: keep
  5. #include <cstddef>
  6. #include <stack>
  7. #include <vector>
  8. #include "cmGraphAdjacencyList.h"
  9. /** \class cmComputeComponentGraph
  10. * \brief Analyze a graph to determine strongly connected components.
  11. *
  12. * Convert a directed graph into a directed acyclic graph whose nodes
  13. * correspond to strongly connected components of the original graph.
  14. *
  15. * We use Tarjan's algorithm to enumerate the components efficiently.
  16. * An advantage of this approach is that the components are identified
  17. * in a topologically sorted order.
  18. */
  19. class cmComputeComponentGraph
  20. {
  21. public:
  22. // Represent the graph with an adjacency list.
  23. using NodeList = cmGraphNodeList;
  24. using EdgeList = cmGraphEdgeList;
  25. using Graph = cmGraphAdjacencyList;
  26. cmComputeComponentGraph(Graph const& input);
  27. ~cmComputeComponentGraph();
  28. /** Run the computation. */
  29. void Compute();
  30. /** Get the adjacency list of the component graph. */
  31. Graph const& GetComponentGraph() const { return this->ComponentGraph; }
  32. EdgeList const& GetComponentGraphEdges(size_t c) const
  33. {
  34. return this->ComponentGraph[c];
  35. }
  36. /** Get map from component index to original node indices. */
  37. std::vector<NodeList> const& GetComponents() const
  38. {
  39. return this->Components;
  40. }
  41. NodeList const& GetComponent(size_t c) const { return this->Components[c]; }
  42. /** Get map from original node index to component index. */
  43. std::vector<size_t> const& GetComponentMap() const
  44. {
  45. return this->TarjanComponents;
  46. }
  47. static const size_t INVALID_COMPONENT;
  48. private:
  49. void TransferEdges();
  50. Graph const& InputGraph;
  51. Graph ComponentGraph;
  52. // Tarjan's algorithm.
  53. struct TarjanEntry
  54. {
  55. size_t Root;
  56. size_t VisitIndex;
  57. };
  58. std::vector<size_t> TarjanVisited;
  59. std::vector<size_t> TarjanComponents;
  60. std::vector<TarjanEntry> TarjanEntries;
  61. std::vector<NodeList> Components;
  62. std::stack<size_t> TarjanStack;
  63. size_t TarjanWalkId;
  64. size_t TarjanIndex;
  65. void Tarjan();
  66. void TarjanVisit(size_t i);
  67. // Connected components.
  68. };