22 throw std::invalid_argument(
23 "IncrementalKCore requires an undirected graph; directed k-core semantics must be selected explicitly");
28 [[nodiscard]]
const std::vector<std::uint32_t>&
core() const noexcept {
return core_; }
33 last_repaired_vertices_ = 0;
38 for (
const auto& e : batch.
updates) {
39 if (e.src <
vertex_count(g_)) mark_component(e.src, affected);
40 if (e.dst <
vertex_count(g_)) mark_component(e.dst, affected);
50 for (
const auto& e : batch.
updates) {
51 if (e.src <
vertex_count(g_)) mark_component(e.src, affected);
52 if (e.dst <
vertex_count(g_)) mark_component(e.dst, affected);
55 recompute_region(affected);
61 std::vector<std::uint8_t> all(n, 1);
62 recompute_region(all);
66 void mark_component(
VertexId seed, std::vector<std::uint8_t>& marked)
const {
67 if (seed >=
vertex_count(g_) || seed >= marked.size() || marked[seed])
return;
68 std::queue<VertexId> q;
72 const auto u = q.front();
75 if (v < marked.size() && !marked[v]) {
83 void recompute_region(
const std::vector<std::uint8_t>& affected) {
85 if (core_.size() < n) core_.resize(n, 0);
87 std::vector<std::uint32_t> degree(n, 0);
88 std::vector<std::uint8_t> removed(n, 0);
89 last_repaired_vertices_ = 0;
91 using Item = std::pair<std::uint32_t, VertexId>;
92 std::priority_queue<Item, std::vector<Item>, std::greater<Item>> heap;
95 if (u >= affected.size() || !affected[u])
continue;
96 ++last_repaired_vertices_;
98 if (v < affected.size() && affected[v]) ++degree[u];
101 heap.push({degree[u], u});
104 std::uint32_t current_core = 0;
105 while (!heap.empty()) {
106 const auto [queued_degree, u] = heap.top();
108 if (u >= n || removed[u] || queued_degree != degree[u])
continue;
111 current_core = std::max(current_core, queued_degree);
112 core_[u] = current_core;
115 if (v >= n || v >= affected.size() || !affected[v] || removed[v])
return;
116 if (degree[v] != 0) --degree[v];
117 heap.push({degree[v], v});
123 std::vector<std::uint32_t> core_;
124 std::size_t last_repaired_vertices_{0};