38 #ifndef UTIL_GRAPH_CONNECTED_COMPONENTS_H_ 39 #define UTIL_GRAPH_CONNECTED_COMPONENTS_H_ 45 #include <type_traits> 48 #include "absl/container/flat_hash_map.h" 49 #include "absl/container/flat_hash_set.h" 50 #include "absl/hash/hash.h" 51 #include "absl/meta/type_traits.h" 52 #include "ortools/base/logging.h" 53 #include "ortools/base/map_util.h" 54 #include "ortools/base/ptr_util.h" 72 template <
class UndirectedGraph>
74 const UndirectedGraph& graph);
92 void AddEdge(
int node1,
int node2);
115 std::vector<int> parent_;
118 std::vector<int> component_size_;
120 std::vector<int> rank_;
122 int num_components_ = 0;
128 template <
typename T,
typename CompareOrHashT>
129 struct ConnectedComponentsTypeHelper {
132 template <
typename U,
typename E =
void>
133 struct SelectContainer {
134 using Set = std::set<T, CompareOrHashT>;
135 using Map = std::map<T, int, CompareOrHashT>;
142 template <
typename U>
143 struct SelectContainer<
144 U, absl::enable_if_t<std::is_integral<decltype(
145 std::declval<const U&>()(std::declval<const T&>()))>::value>> {
146 using Set = absl::flat_hash_set<T, CompareOrHashT>;
147 using Map = absl::flat_hash_map<T, int, CompareOrHashT>;
150 using Set =
typename SelectContainer<CompareOrHashT>::Set;
151 using Map =
typename SelectContainer<CompareOrHashT>::Map;
188 template <
typename T,
typename CompareOrHashT = std::less<T>>
200 void AddNode(T node) { LookupOrInsertNode<true>(node); }
205 delegate_.
AddEdge(LookupOrInsertNode<false>(node1),
206 LookupOrInsertNode<false>(node2));
212 return delegate_.
Connected(gtl::FindWithDefault(index_, node1, -1),
213 gtl::FindWithDefault(index_, node2, -1));
220 return delegate_.
GetSize(gtl::FindWithDefault(index_, node, -1));
235 for (
const auto& elem_id : index_) {
236 components[component_ids[elem_id.second]].push_back(elem_id.first);
241 std::vector<
typename internal::ConnectedComponentsTypeHelper<
242 T, CompareOrHashT>::Set>* components) {
246 for (
const auto& elem_id : index_) {
247 components->at(component_ids[elem_id.second]).insert(elem_id.first);
266 template <
bool update_delegate>
267 int LookupOrInsertNode(T node) {
268 const auto result = index_.emplace(node, index_.size());
269 const int node_id = result.first->second;
270 if (update_delegate && result.second) {
278 typename internal::ConnectedComponentsTypeHelper<T, CompareOrHashT>::Map
286 template <
class UndirectedGraph>
288 const UndirectedGraph& graph) {
289 std::vector<int> component_of_node(num_nodes, -1);
290 std::vector<int> bfs_queue;
291 int num_components = 0;
292 for (
int src = 0; src < num_nodes; ++src) {
293 if (component_of_node[src] >= 0)
continue;
294 bfs_queue.push_back(src);
295 component_of_node[src] = num_components;
296 for (
int num_visited = 0; num_visited < bfs_queue.size(); ++num_visited) {
297 const int node = bfs_queue[num_visited];
298 for (
const int neighbor : graph[node]) {
299 if (component_of_node[neighbor] >= 0)
continue;
300 component_of_node[neighbor] = num_components;
301 bfs_queue.push_back(neighbor);
307 return component_of_node;
311 #endif // UTIL_GRAPH_CONNECTED_COMPONENTS_H_ void AddEdge(T node1, T node2)
Adds an edge in the graph.
void AddNode(T node)
Adds a node in the graph.
bool Connected(int node1, int node2)
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in c...
ConnectedComponentsFinder()
Constructs a connected components finder.
int GetSize(T node)
Finds the connected component containing a node, and returns the total number of nodes in that compon...
void SetNumberOfNodes(int num_nodes)
Sets the number of nodes in the graph.
std::vector< std::vector< T > > FindConnectedComponents()
Finds all the connected components and assigns them to components.
DenseConnectedComponentsFinder()
NOTE(user): The rest of the functions below should also be in namespace util, but for historical reas...
std::vector< int > GetConnectedComponents(int num_nodes, const UndirectedGraph &graph)
Finds the connected components of the graph, using BFS internally.
int GetNumberOfNodes() const
Returns the current number of added distinct nodes.
int GetNumberOfNodes() const
bool Connected(T node1, T node2)
Returns true iff both nodes are in the same connected component.
int GetNumberOfComponents() const
Returns the current number of connected components.
ConnectedComponentsFinder & operator=(const ConnectedComponentsFinder &)=delete
int GetNumberOfComponents() const
Usage: ConnectedComponentsFinder<MyNodeType> cc; cc.AddNode(node1); cc.AddNode(node2); cc....
std::vector< int > GetComponentIds()
Returns the same as GetConnectedComponents().
DenseConnectedComponentsFinder & operator=(const DenseConnectedComponentsFinder &)=delete
void FindConnectedComponents(std::vector< typename internal::ConnectedComponentsTypeHelper< T, CompareOrHashT >::Set > *components)
void AddEdge(int node1, int node2)
The main API is the same as ConnectedComponentsFinder (below): see the homonymous functions there.
int FindRoot(int node)
Returns the root of the set for the given node.