This documentation is automatically generated by online-judge-tools/verification-helper
#include "Src/Graph/Components/IncrementalSCC.hpp"
$M$ 要素からなる有向辺の列 $E = ((u_{1}, v_{1}), (u_{2}, v_{2}), \dots, (u_{M}, v_{M}))$ が与えられる。
$N$ 頂点 $0$ 辺のグラフ $G$ に対して $E$ の辺をこの順に追加していく。
$E$ の各辺 $(u_{i}, v_{i})$ についてその辺の両端点が強連結になる時間を計算する。
(1) IncrementalSCC() = default;
(2) IncrementalSCC(usize n)
(2) $n$ 頂点 $0$ 辺のグラフを用意する。 $E = ()$ とする。
inline u32 size() const noexcept
グラフの頂点数を返す。
u32 addEdge(VType u, VType v)
VType = u32
$E$ の末尾に $u$ から $v$ へ伸びる辺を追加する。この辺が何番目に追加された辺かを0-indexedで返す。
std::pair<VType, VType> getEdge(TimeType t) const
0-indexedで $t$ 番目に追加された辺を返す。firstからsecondへ向けて張られた辺である。
IncrementalSCCResponse build() const
$E$ の各辺 $(u_{i}, v_{i})$ について、頂点 $u_{i}, v_{i}$ が強連結になる時間を計算する。
計算量: $O( | E | \log | E | )$ |
static constexpr TimeType invalid() noexcept
最後まで強連結にならないことを示す特別な値を返す。
TimeType operator[](u32 i) const noexcept
$(u_{i}, v_{i})$ について頂点 $u_{i}, v_{i}$ が強連結になる時間を返す。
厳密には、 $E$ の $0$ 番目から $t$ 番目までの辺を追加すると $u_{i}, v_{i}$ が強連結になるような最小の $t$ を返す。
そのような $t$ が存在しなければinvalid()
を返す。
計算量: $O(1)$
bool same(u32 i) const noexcept
$(u_{i}, v_{i})$ が最終的に強連結になるかを返す。
$(u_{i}, v_{i})$ が強連結になる時間を $T_{i}$ とする。
頂点 $u_{i}, v_{i}$ にコスト $T_{i}$ の無向辺を張ったグラフを考える。
このグラフ上で最小全域木を張る。 木上の $u-v$ パスに含まれるコスト最大の辺のコスト $T$ が頂点 $u, v$ が強連結になる時間と一致する。
#pragma once
#include "../../Template/TypeAlias.hpp"
#include "atcoder/scc.hpp"
#include <algorithm>
#include <cassert>
#include <utility>
#include <vector>
namespace zawa {
class IncrementalSCCResponse {
public:
using TimeType = u32;
static constexpr TimeType invalid() noexcept {
return INVALID;
}
IncrementalSCCResponse() = default;
IncrementalSCCResponse(const std::vector<TimeType>& T) : time_{T} {
time_.shrink_to_fit();
}
TimeType operator[](u32 i) const noexcept {
assert(i < time_.size());
return time_[i];
}
bool same(u32 i) const noexcept {
return time_[i] != INVALID;
}
private:
static constexpr TimeType INVALID{static_cast<TimeType>(-1)};
std::vector<TimeType> time_;
};
class IncrementalSCC {
private:
using TimeType = IncrementalSCCResponse::TimeType;
using VType = u32;
using Edge = std::tuple<TimeType, VType, VType>;
static constexpr u32 INVALID{IncrementalSCCResponse::invalid()};
usize n_;
std::vector<Edge> edges_;
public:
IncrementalSCC() = default;
IncrementalSCC(usize n) : n_{n}, edges_{} {}
inline u32 size() const noexcept {
return n_;
}
constexpr u32 invalid() const noexcept {
return INVALID;
}
u32 addEdge(VType u, VType v) {
assert(u < n_);
assert(v < n_);
TimeType t{static_cast<TimeType>(edges_.size())};
edges_.emplace_back(t, u, v);
return t;
}
std::pair<VType, VType> getEdge(TimeType t) const {
assert(t < edges_.size());
auto [_, u, v]{edges_[t]};
return std::pair<VType, VType>{ u, v };
}
IncrementalSCCResponse build() const {
std::vector<VType> id(size(), INVALID);
std::vector<TimeType> res(edges_.size(), INVALID);
auto rec{[&](auto rec, u32 L, u32 R, const std::vector<Edge>& E) -> void {
if (E.empty() or L + 1 >= R) {
return;
}
u32 n{};
for (auto [t, u, v] : E) {
if (id[u] == INVALID) {
id[u] = n++;
}
if (id[v] == INVALID) {
id[v] = n++;
}
}
u32 mid{(L + R) >> 1};
atcoder::scc_graph g(n);
for (auto [t, u, v] : E) {
if (t < mid) {
g.add_edge(id[u], id[v]);
}
}
auto scc{g.scc()};
std::vector<u32> comp(n);
for (u32 i{} ; i < scc.size() ; i++) {
for (auto v : scc[i]) {
comp[v] = i;
}
}
std::vector<Edge> EL, ER;
for (auto [t, u, v] : E) {
u = id[u];
v = id[v];
if (t < mid and comp[u] == comp[v]) {
res[t] = std::min(res[t], mid - 1);
EL.emplace_back(t, u, v);
}
else {
ER.emplace_back(t, comp[u], comp[v]);
}
}
for (auto [_, u, v] : E) {
id[u] = id[v] = INVALID;
}
rec(rec, L, mid, EL);
rec(rec, mid, R, ER);
}};
rec(rec, u32{}, edges_.size() + 1, edges_);
return IncrementalSCCResponse{res};
}
};
} // namespace zawa
Traceback (most recent call last):
File "/opt/hostedtoolcache/Python/3.13.5/x64/lib/python3.13/site-packages/onlinejudge_verify/documentation/build.py", line 71, in _render_source_code_stat
bundled_code = language.bundle(stat.path, basedir=basedir, options={'include_paths': [basedir]}).decode()
~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/hostedtoolcache/Python/3.13.5/x64/lib/python3.13/site-packages/onlinejudge_verify/languages/cplusplus.py", line 187, in bundle
bundler.update(path)
~~~~~~~~~~~~~~^^^^^^
File "/opt/hostedtoolcache/Python/3.13.5/x64/lib/python3.13/site-packages/onlinejudge_verify/languages/cplusplus_bundle.py", line 401, in update
self.update(self._resolve(pathlib.Path(included), included_from=path))
~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/hostedtoolcache/Python/3.13.5/x64/lib/python3.13/site-packages/onlinejudge_verify/languages/cplusplus_bundle.py", line 260, in _resolve
raise BundleErrorAt(path, -1, "no such header")
onlinejudge_verify.languages.cplusplus_bundle.BundleErrorAt: atcoder/scc.hpp: line -1: no such header