Skip to content

complement_graph_components.hpp

SECTIONGraph INCLUDEnoya/complement_graph_components.hpp

Connected components of the complement of an undirected graph.

Verified by connected_components_of_complement_graph.

在线性对数级复杂度内求补图的连通分量,而不显式建立所有补边。

Implementation

View on GitHub

#ifndef NOYA_COMPLEMENT_GRAPH_COMPONENTS_HPP
#define NOYA_COMPLEMENT_GRAPH_COMPONENTS_HPP 1

/// @complexity Time: O(V + E).
/// Space: O(V + E).

#include <cassert>
#include <list>
#include <queue>
#include <utility>
#include <vector>

namespace noya {

/// @brief Connected components of the complement of an undirected graph.
inline std::vector<std::vector<int>>
complement_graph_components(int vertex_count,
                            const std::vector<std::pair<int, int>> &edges) {
  assert(vertex_count >= 0);
  std::vector<std::vector<int>> graph(vertex_count);
  for (auto [first, second] : edges) {
    assert(0 <= first && first < vertex_count);
    assert(0 <= second && second < vertex_count);
    graph[first].push_back(second);
    graph[second].push_back(first);
  }

  std::list<int> unvisited;
  for (int vertex = 0; vertex < vertex_count; vertex++) {
    unvisited.push_back(vertex);
  }
  std::vector<int> neighbor_stamp(vertex_count);
  int stamp = 0;
  std::vector<std::vector<int>> components;
  while (!unvisited.empty()) {
    int start = unvisited.front();
    unvisited.pop_front();
    components.push_back({start});
    std::queue<int> queue;
    queue.push(start);
    while (!queue.empty()) {
      int vertex = queue.front();
      queue.pop();
      ++stamp;
      for (int next : graph[vertex]) {
        neighbor_stamp[next] = stamp;
      }
      for (auto iterator = unvisited.begin(); iterator != unvisited.end();) {
        int candidate = *iterator;
        if (neighbor_stamp[candidate] == stamp) {
          ++iterator;
        } else {
          components.back().push_back(candidate);
          queue.push(candidate);
          iterator = unvisited.erase(iterator);
        }
      }
    }
  }
  return components;
}

} // namespace noya

#endif // NOYA_COMPLEMENT_GRAPH_COMPONENTS_HPP
#include <cassert>
#include <list>
#include <queue>
#include <utility>
#include <vector>

/// @complexity Time: O(V + E).
/// Space: O(V + E).

namespace noya {

/// @brief Connected components of the complement of an undirected graph.
inline std::vector<std::vector<int>>
complement_graph_components(int vertex_count,
                            const std::vector<std::pair<int, int>> &edges) {
  assert(vertex_count >= 0);
  std::vector<std::vector<int>> graph(vertex_count);
  for (auto [first, second] : edges) {
    assert(0 <= first && first < vertex_count);
    assert(0 <= second && second < vertex_count);
    graph[first].push_back(second);
    graph[second].push_back(first);
  }

  std::list<int> unvisited;
  for (int vertex = 0; vertex < vertex_count; vertex++) {
    unvisited.push_back(vertex);
  }
  std::vector<int> neighbor_stamp(vertex_count);
  int stamp = 0;
  std::vector<std::vector<int>> components;
  while (!unvisited.empty()) {
    int start = unvisited.front();
    unvisited.pop_front();
    components.push_back({start});
    std::queue<int> queue;
    queue.push(start);
    while (!queue.empty()) {
      int vertex = queue.front();
      queue.pop();
      ++stamp;
      for (int next : graph[vertex]) {
        neighbor_stamp[next] = stamp;
      }
      for (auto iterator = unvisited.begin(); iterator != unvisited.end();) {
        int candidate = *iterator;
        if (neighbor_stamp[candidate] == stamp) {
          ++iterator;
        } else {
          components.back().push_back(candidate);
          queue.push(candidate);
          iterator = unvisited.erase(iterator);
        }
      }
    }
  }
  return components;
}

} // namespace noya