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"
72 template <
class UndirectedGraph>
74 const UndirectedGraph& graph);
92 void AddEdge(
int node1,
int node2);
119 std::vector<int> parent_;
122 std::vector<int> component_size_;
124 std::vector<int> rank_;
126 int num_components_ = 0;
128 std::vector<int> roots_;
131 int num_nodes_at_last_get_roots_call_ = 0;
137 template <
typename T,
typename CompareOrHashT>
141 template <
typename U,
typename E =
void>
143 using Set = std::set<T, CompareOrHashT>;
144 using Map = std::map<T, int, CompareOrHashT>;
151 template <
typename U>
153 U,
absl::enable_if_t<std::is_integral<decltype(std::declval<const U&>()(
154 std::declval<const T&>()))>::value>> {
155 using Set = absl::flat_hash_set<T, CompareOrHashT>;
156 using Map = absl::flat_hash_map<T, int, CompareOrHashT>;
197 template <
typename T,
typename CompareOrHashT = std::less<T>>
209 void AddNode(T node) { LookupOrInsertNode<true>(node); }
214 delegate_.
AddEdge(LookupOrInsertNode<false>(node1),
215 LookupOrInsertNode<false>(node2));
244 for (
const auto& elem_id : index_) {
245 components[component_ids[elem_id.second]].push_back(elem_id.first);
251 T, CompareOrHashT>::Set>* components) {
255 for (
const auto& elem_id : index_) {
256 components->at(component_ids[elem_id.second]).insert(elem_id.first);
275 template <
bool update_delegate>
276 int LookupOrInsertNode(T node) {
277 const auto result = index_.emplace(node, index_.size());
278 const int node_id = result.first->second;
279 if (update_delegate && result.second) {
295 template <
class UndirectedGraph>
297 const UndirectedGraph& graph) {
298 std::vector<int> component_of_node(num_nodes, -1);
299 std::vector<int> bfs_queue;
300 int num_components = 0;
301 for (
int src = 0; src < num_nodes; ++src) {
302 if (component_of_node[src] >= 0)
continue;
303 bfs_queue.push_back(src);
304 component_of_node[src] = num_components;
305 for (
int num_visited = 0; num_visited < bfs_queue.size(); ++num_visited) {
306 const int node = bfs_queue[num_visited];
307 for (
const int neighbor : graph[node]) {
308 if (component_of_node[neighbor] >= 0)
continue;
309 component_of_node[neighbor] = num_components;
310 bfs_queue.push_back(neighbor);
316 return component_of_node;
320 #endif // UTIL_GRAPH_CONNECTED_COMPONENTS_H_