4#include <unordered_set>
5#include <unordered_map>
10#include "zen/config.hpp"
17template<
typename V,
typename L = no_label_t>
31 std::unordered_set<V> vertices;
33 std::unordered_multimap<V, out_edge_t> out_edges;
37 using vertex_type = V;
40 void add_vertex(V vertex) {
41 vertices.emplace(vertex);
44 void add_edge(V from, V to, L label) {
45 ZEN_ASSERT(vertices.count(from));
46 ZEN_ASSERT(vertices.count(to));
47 out_edges.emplace(from, out_edge_t { label, to });
50 void add_edge(V from, V to)
requires (std::is_same_v<L, no_label_t>) {
51 ZEN_ASSERT(vertices.count(from));
52 ZEN_ASSERT(vertices.count(to));
53 out_edges.emplace(from, out_edge_t { {}, to });
56 std::vector<V> get_target_vertices(
const V& from)
const {
59 out.push_back(edge.vertex);
64 std::size_t count_vertices() {
65 return vertices.size();
72 auto get_vertices()
const {
115std::vector<typename G::vertex_type> dijkstra(
const G& graph) {
119template<
typename Graph>
120std::vector<std::vector<typename Graph::vertex_type>> toposort(
const Graph& graph) {
122 using V =
typename Graph::vertex_type;
124 struct TarjanVertexData {
125 std::optional<std::size_t> index;
126 std::size_t low_link;
127 bool on_stack =
false;
133 std::vector<std::vector<V>> components;
138 std::unordered_map<V, TarjanVertexData> mapping;
139 std::size_t index = 0;
142 TarjanVertexData& get_data(V from) {
143 return mapping.emplace(from, TarjanVertexData {}).first->second;
146 void visit_cycle(
const V& from) {
148 auto& data_from = get_data(from);
149 data_from.index = index;
150 data_from.low_link = index;
153 data_from.on_stack =
true;
155 for (
const auto& to: graph.get_target_vertices(from)) {
156 auto& data_to = get_data(to);
157 if (!data_to.index) {
159 data_from.low_link = std::min(data_from.low_link, data_to.low_link);
160 }
else if (data_to.on_stack) {
161 data_from.low_link = std::min(data_from.low_link, *data_to.index);
165 if (data_from.low_link == data_from.index) {
166 std::vector<V> component;
168 auto& X = stack.top();
170 auto& data_x = get_data(X);
171 data_x.on_stack =
false;
172 component.push_back(X);
177 components.push_back(component);
184 TarjanSolver(
const Graph& graph):
188 for (
auto from: graph.get_vertices()) {
189 if (!mapping.count(from)) {
197 TarjanSolver S { graph };
Support for creating ranges over iterators.
auto make_iterator_range(IterT &&a, IterT &&b)
Definition iterator_range.hpp:92