25#ifndef UTIL_GRAPH_CONNECTED_COMPONENTS_H_
26#define UTIL_GRAPH_CONNECTED_COMPONENTS_H_
35#include "absl/container/flat_hash_map.h"
36#include "absl/container/flat_hash_set.h"
37#include "absl/hash/hash.h"
38#include "absl/meta/type_traits.h"
45template <
class UndirectedGraph,
class NodeType>
47 const UndirectedGraph&
graph);
64template <
class UndirectedGraph>
66 const UndirectedGraph&
graph) {
90 bool AddEdge(
int node1,
int node2);
121 std::vector<int> parent_;
124 std::vector<int> component_size_;
126 std::vector<int> rank_;
128 int num_components_ = 0;
130 std::vector<int> roots_;
133 int num_nodes_at_last_get_roots_call_ = 0;
139template <
typename T,
typename CompareOrHashT,
typename Eq>
143 template <
typename U,
typename V,
typename E =
void>
145 using Set = std::set<T, CompareOrHashT>;
146 using Map = std::map<T, int, CompareOrHashT>;
155 template <
typename U,
typename V>
158 absl::enable_if_t<std::is_integral<decltype(std::declval<const U&>()(
159 std::declval<const T&>()))>::value &&
160 std::is_same_v<V, void>>> {
161 using Set = absl::flat_hash_set<T, CompareOrHashT>;
162 using Map = absl::flat_hash_map<T, int, CompareOrHashT>;
166 template <
typename U,
typename V>
169 absl::enable_if_t<std::is_integral<decltype(std::declval<const U&>()(
170 std::declval<const T&>()))>::value &&
171 !std::is_same_v<V, void>>> {
172 using Set = absl::flat_hash_set<T, CompareOrHashT, Eq>;
173 using Map = absl::flat_hash_map<T, int, CompareOrHashT, Eq>;
218template <
typename T,
typename CompareOrHashT = std::less<T>,
235 void AddNode(T node) { LookupOrInsertNode<true>(node); }
242 return delegate_.AddEdge(LookupOrInsertNode<false>(node1),
243 LookupOrInsertNode<false>(node2));
270 const auto component_ids = delegate_.GetComponentIds();
271 std::vector<std::vector<T>> components(delegate_.GetNumberOfComponents());
272 for (
const auto& elem_id : index_) {
273 components[component_ids[elem_id.second]].push_back(elem_id.first);
278 const auto component_ids = delegate_.GetComponentIds();
280 components->resize(delegate_.GetNumberOfComponents());
281 for (
const auto& elem_id : index_) {
282 components->at(component_ids[elem_id.second]).insert(elem_id.first);
289 return delegate_.GetNumberOfComponents();
301 template <
bool update_delegate>
302 int LookupOrInsertNode(T node) {
303 const auto result = index_.emplace(node, index_.size());
304 const int node_id = result.first->second;
305 if (update_delegate && result.second) {
312 DenseConnectedComponentsFinder delegate_;
321template <
class UndirectedGraph,
typename NodeType>
323 const UndirectedGraph&
graph) {
326 std::vector<NodeType> component_of_node(num_nodes, num_nodes);
327 std::vector<NodeType> bfs_queue;
328 NodeType num_components = 0;
329 for (NodeType src = 0; src < num_nodes; ++src) {
330 if (component_of_node[src] != num_nodes)
continue;
331 bfs_queue.push_back(src);
332 component_of_node[src] = num_components;
333 for (
size_t num_visited = 0; num_visited < bfs_queue.size();
335 const NodeType node = bfs_queue[num_visited];
336 for (
const NodeType neighbor :
graph[node]) {
337 if (component_of_node[neighbor] != num_nodes)
continue;
338 component_of_node[neighbor] = num_components;
339 bfs_queue.push_back(neighbor);
345 return component_of_node;
ConnectedComponentsFinder()=default
ConnectedComponentsFinder(const ConnectedComponentsFinder &)=delete
int GetNumberOfComponents() const
typename internal::ConnectedComponentsTypeHelper< T, CompareOrHashT, Eq >::Set Set
int GetNumberOfNodes() const
bool Connected(T node1, T node2)
void FindConnectedComponents(std::vector< Set > *components)
std::vector< std::vector< T > > FindConnectedComponents()
bool AddEdge(T node1, T node2)
ConnectedComponentsFinder & operator=(const ConnectedComponentsFinder &)=delete
bool Connected(int node1, int node2)
DenseConnectedComponentsFinder()=default
bool AddEdge(int node1, int node2)
int GetNumberOfNodes() const
void SetNumberOfNodes(int num_nodes)
int GetNumberOfComponents() const
int GetParent(int node) const
DenseConnectedComponentsFinder(const DenseConnectedComponentsFinder &)=default
std::vector< int > GetComponentIds()
DenseConnectedComponentsFinder & operator=(DenseConnectedComponentsFinder &&)=default
DenseConnectedComponentsFinder & operator=(const DenseConnectedComponentsFinder &)=default
const std::vector< int > & GetComponentRoots()
DenseConnectedComponentsFinder(DenseConnectedComponentsFinder &&)=default
const MapUtilMappedT< Collection > & FindWithDefault(const Collection &collection, const KeyType &key, const MapUtilMappedT< Collection > &value)
std::vector< int > GetConnectedComponents(int num_nodes, const UndirectedGraph &graph)
std::vector< NodeType > GetConnectedComponentsTpl(NodeType num_nodes, const UndirectedGraph &graph)
absl::flat_hash_set< T, CompareOrHashT > Set
absl::flat_hash_map< T, int, CompareOrHashT > Map
absl::flat_hash_map< T, int, CompareOrHashT, Eq > Map
absl::flat_hash_set< T, CompareOrHashT, Eq > Set
std::set< T, CompareOrHashT > Set
std::map< T, int, CompareOrHashT > Map
typename SelectContainer< CompareOrHashT, Eq >::Set Set
typename SelectContainer< CompareOrHashT, Eq >::Map Map