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);
96 bool AddEdge(
int node1,
int node2);
123 std::vector<int> parent_;
126 std::vector<int> component_size_;
128 std::vector<int> rank_;
130 int num_components_ = 0;
132 std::vector<int> roots_;
135 int num_nodes_at_last_get_roots_call_ = 0;
141 template <
typename T,
typename CompareOrHashT>
145 template <
typename U,
typename E =
void>
147 using Set = std::set<T, CompareOrHashT>;
148 using Map = std::map<T, int, CompareOrHashT>;
155 template <
typename U>
157 U,
absl::enable_if_t<std::is_integral<decltype(std::declval<const U&>()(
158 std::declval<const T&>()))>::value>> {
159 using Set = absl::flat_hash_set<T, CompareOrHashT>;
160 using Map = absl::flat_hash_map<T, int, CompareOrHashT>;
201 template <
typename T,
typename CompareOrHashT = std::less<T>>
213 void AddNode(T node) { LookupOrInsertNode<true>(node); }
220 return delegate_.
AddEdge(LookupOrInsertNode<false>(node1),
221 LookupOrInsertNode<false>(node2));
250 for (
const auto& elem_id : index_) {
251 components[component_ids[elem_id.second]].push_back(elem_id.first);
257 T, CompareOrHashT>::Set>* components) {
261 for (
const auto& elem_id : index_) {
262 components->at(component_ids[elem_id.second]).insert(elem_id.first);
281 template <
bool update_delegate>
282 int LookupOrInsertNode(T node) {
283 const auto result = index_.emplace(node, index_.size());
284 const int node_id = result.first->second;
285 if (update_delegate && result.second) {
301 template <
class UndirectedGraph>
303 const UndirectedGraph& graph) {
304 std::vector<int> component_of_node(num_nodes, -1);
305 std::vector<int> bfs_queue;
306 int num_components = 0;
307 for (
int src = 0; src < num_nodes; ++src) {
308 if (component_of_node[src] >= 0)
continue;
309 bfs_queue.push_back(src);
310 component_of_node[src] = num_components;
311 for (
int num_visited = 0; num_visited < bfs_queue.size(); ++num_visited) {
312 const int node = bfs_queue[num_visited];
313 for (
const int neighbor : graph[node]) {
314 if (component_of_node[neighbor] >= 0)
continue;
315 component_of_node[neighbor] = num_components;
316 bfs_queue.push_back(neighbor);
322 return component_of_node;
326 #endif // UTIL_GRAPH_CONNECTED_COMPONENTS_H_ absl::flat_hash_map< T, int, CompareOrHashT > Map
DenseConnectedComponentsFinder & operator=(const DenseConnectedComponentsFinder &)=default
std::vector< std::vector< T > > FindConnectedComponents()
ConnectedComponentsFinder & operator=(const ConnectedComponentsFinder &)=delete
bool AddEdge(T node1, T node2)
bool Connected(int node1, int node2)
int GetNumberOfNodes() const
DenseConnectedComponentsFinder()
ConnectedComponentsFinder()
typename SelectContainer< CompareOrHashT >::Map Map
std::vector< int > GetComponentIds()
int GetNumberOfNodes() const
std::vector< int > GetConnectedComponents(int num_nodes, const UndirectedGraph &graph)
const std::vector< int > & GetComponentRoots()
absl::flat_hash_set< T, CompareOrHashT > Set
void SetNumberOfNodes(int num_nodes)
int GetNumberOfComponents() const
const Collection::value_type::second_type & FindWithDefault(const Collection &collection, const typename Collection::value_type::first_type &key, const typename Collection::value_type::second_type &value)
typename SelectContainer< CompareOrHashT >::Set Set
int GetNumberOfComponents() const
std::set< T, CompareOrHashT > Set
void FindConnectedComponents(std::vector< typename internal::ConnectedComponentsTypeHelper< T, CompareOrHashT >::Set > *components)
bool AddEdge(int node1, int node2)
bool Connected(T node1, T node2)
std::map< T, int, CompareOrHashT > Map