2#include <__expected/unexpected.h>
11#include <unordered_map>
12#include <unordered_set>
25 { std::hash<T>{}(a) } -> std::convertible_to<std::size_t>;
29template <
class NodeType,
class CounterType>
33template <
class Aspect,
class CounterType,
class H>
class Counter;
38template <
class NodeType,
class Cost = float_t,
39 class CounterType = std::uint16_t,
47template <
class NodeType,
class Cost = float_t,
48 class CounterType = std::uint16_t,
54template <
class NodeType,
class Cost = float_t,
55 class CounterType = std::uint16_t,
61template <
class CounterType,
class H = DefaultHashMap<CounterType, CounterType>>
69template <
class CounterType,
class Cost>
70using CounterEdge = std::tuple<CounterType, CounterType, Cost>;
71template <
class CounterType>
73template <
class CounterType,
class Cost>
76template <
class CounterType,
class Cost>
77using Edge = std::tuple<CounterType, CounterType, Cost>;
113template <
class Aspect,
class CounterType,
class H>
class Counter {
118 explicit Counter(CounterType start_from) : count(start_from) {}
119 bool exist(
const Aspect &aspect)
const {
120 return counter.find(aspect) != counter.end();
125 if (not
exist(aspect))
126 counter[aspect] = count++;
127 return counter[aspect];
132template <
class CounterType,
class Cost>
class EdgeIte {};
135template <
class NodeType,
class Cost,
class CounterType,
class H>
140 std::unordered_map<CounterType, std::set<CounterHalfEdge<CounterType, Cost>>>
145 template <VisitOrder v>
148 std::optional<std::reference_wrapper<std::unordered_set<CounterType>>>
149 pre_visited = std::nullopt)
const -> std::vector<CounterType> {
150 using tup = std::tuple<CounterType, VisitOrder>;
151 std::stack<tup> stck;
152 std::unordered_set<CounterType> local_visited;
153 std::unordered_set<CounterType> &visited =
154 pre_visited.has_value() ? pre_visited->get() : local_visited;
155 std::vector<CounterType> result;
160 while (not stck.empty()) {
161 auto [current_node, visit_order] = stck.top();
163 visited.insert(current_node);
167 result.push_back(current_node);
170 auto neighbors =
graph.find(current_node);
171 if (neighbors ==
graph.end())
173 for (
auto &[neighbor, cost] : (*neighbors).second) {
174 if (visited.contains(neighbor))
179 result.push_back(current_node);
185 template <VisitOrder v>
188 std::optional<std::reference_wrapper<std::unordered_set<CounterType>>>
189 pre_visited = std::nullopt)
const -> std::vector<CounterType> {
190 using tup = std::tuple<CounterType, VisitOrder>;
192 std::unordered_set<CounterType> local_visited;
193 std::unordered_set<CounterType> &visited =
194 pre_visited.has_value() ? pre_visited->get() : local_visited;
195 std::vector<CounterType> result;
200 while (not q.empty()) {
201 auto [current_node, visit_order] = q.front();
203 visited.insert(current_node);
207 result.push_back(current_node);
210 auto neighbors =
graph.find(current_node);
211 if (neighbors ==
graph.end())
213 for (
auto &[neighbor, cost] : (*neighbors).second) {
214 if (visited.contains(neighbor))
219 result.push_back(current_node);
233 const auto [from, to, cost] = edge;
236 this->
graph[from].insert({to, cost});
241 -> std::optional<edge_error> {
245 const auto &[from, to, old_cost] = edge;
247 this->
graph[from].erase({to, old_cost});
251 this->
graph[from].insert({to, new_cost});
256 auto &[from, to, cost] = edge;
259 auto s = this->
graph.find(from);
260 if (s == this->
graph.end())
263 return (*s).second.contains({to, cost});
267 auto from = std::get<0>(edge), to = std::get<1>(edge);
271 auto s = this->
graph.find(from);
272 if (s == this->
graph.end())
275 auto st = (*s).second;
276 return std::find_if(st.begin(), st.end(), [=](
const auto &p) {
277 return to == std::get<0>(p);
281 auto [from, to, cost] = edge;
289 decltype(
edges()) result;
290 for (
auto &[node, neighbors_info] : this->
graph) {
291 for (
auto &[to_neighbor, cost] : neighbors_info) {
292 result.push_back({node, to_neighbor, cost});
299 template <VisitOrder v>
300 [[nodiscard(
"\nDON'T DISCARD THE RESULT OF dfs() - DEPTH FIRST "
301 "SEARCH ON THE WHOLE GRAPH.\n")]]
302 auto dfs() const -> std::vector<CounterType> {
303 std::unordered_set<CounterType> visited;
304 std::vector<CounterType> result;
305 for (
auto [node, st] :
graph) {
306 if (not visited.contains(node))
307 result.insert_range(result.end(),
316 template <VisitOrder v>
317 [[nodiscard(
"\nDON'T DISCARD THE RESULT OF bfs() - BREADTH FIRST "
318 "SEARCH ON THE WHOLE GRAPH.\n")]]
319 auto bfs() const -> std::vector<CounterType> {
320 std::unordered_set<CounterType> visited;
321 std::vector<CounterType> result;
322 for (
auto [node, st] :
graph) {
323 if (not visited.contains(node))
324 result.insert_range(result.end(),
332 template <VisitOrder v>
333 [[nodiscard(
"\nDON'T DISCARD THE RESULT OF explore_dfs() - DEPTH FIRST "
334 "SEARCH OF A SINGULAR NODE.\n")]]
335 auto explore_dfs(CounterType from)
const -> std::vector<CounterType> {
341 template <VisitOrder v>
342 [[nodiscard(
"\nDON'T DISCARD THE RESULT OF explore_bfs() - BREADTH FIRST "
343 "SEARCH OF A SINGULAR NODE.\n")]]
344 auto explore_bfs(CounterType from)
const -> std::vector<CounterType> {
349 [[nodiscard(
"\nDON'T DISCARD THE RESULT OF cycles(), WHICH RETURNS A VECTOR "
350 "OF ELEMENTARY CYCLES\n")]]
352 -> std::vector<std::vector<CounterType>> {
361 "\nDon't discard the result of djikstra's singular shorest path.\n")]]
363 CounterType end)
const
364 -> std::pair<std::unordered_map<CounterType, Cost>,
365 std::unordered_map<CounterType, CounterType>> {
368 std::unordered_map<CounterType, Cost> dist_from_start;
369 std::unordered_map<CounterType, CounterType> prev;
370 dist_from_start[start] = 0;
371 std::priority_queue<std::tuple<Cost, CounterType>,
372 std::vector<std::tuple<Cost, CounterType>>,
373 decltype(std::greater<>())>
374 pq(std::greater<>{});
376 pq.emplace(dist_from_start[start], start);
377 while (not pq.empty()) {
378 auto [dist_node, node] = pq.top();
381 for (
auto [neighbor, cost] : (*
graph.find(node)).second) {
382 if (not dist_from_start.contains(neighbor) or
383 (dist_from_start[neighbor] > dist_from_start[node] + cost)) {
384 dist_from_start[neighbor] = dist_from_start[node] + cost;
385 prev[neighbor] = node;
386 pq.emplace(dist_from_start[neighbor], neighbor);
391 if (not prev.contains(end))
394 return {dist_from_start, prev};
402 [[nodiscard(
"\nDon't discard the result of bellman_ford\n")]]
404 -> std::pair<std::unordered_map<CounterType, Cost>,
405 std::unordered_map<CounterType, CounterType>>
const {
406 std::unordered_map<CounterType, Cost> cost_map;
407 std::unordered_map<CounterType, CounterType> prev;
411 auto num_vertex_minus_1 = this->num_node - 1;
413 while (num_vertex_minus_1) {
414 for (
auto &[from, to, cost] :
edges) {
415 if (not cost_map.contains(from) && not cost_map.contains(to))
417 if (not cost_map.contains(from))
420 auto &a = cost_map[from];
421 auto b = cost_map.contains(to) ? cost_map[to]
422 : std::numeric_limits<Cost>::max();
430 num_vertex_minus_1--;
432 for (
auto &[from, to, cost] :
edges) {
433 if (not cost_map.contains(from) && not cost_map.contains(to))
435 if (not cost_map.contains(from))
438 auto &a = cost_map[from];
439 auto b = cost_map.contains(to) ? cost_map[to]
440 : std::numeric_limits<Cost>::max();
447 return {cost_map, prev};
451 auto scc() -> std::vector<DiGraph>
const;
452 template <
class CT,
class Cst>
friend class EdgeIte;
459template <
class NodeType,
class Cost,
class CounterType,
class H>
466 std::ranges::reverse(dfs_result);
471 CounterType end)
const
472 -> std::pair<std::unordered_map<CounterType, Cost>,
473 std::unordered_map<CounterType, CounterType>>
override {
477 std::unordered_map<CounterType, Cost> dist_from_start;
478 std::unordered_map<CounterType, CounterType> prev;
479 dist_from_start[start] = 0;
481 auto linearized_graph_nodes = this->
topo_sort();
483 for (
auto node : linearized_graph_nodes) {
484 for (
auto [neighbor, cost] : (*this->
graph.find(node)).second) {
486 if (not dist_from_start.contains(neighbor) or
487 (dist_from_start[neighbor] > dist_from_start[node] + cost)) {
488 dist_from_start[neighbor] = dist_from_start[node] + cost;
489 prev[neighbor] = node;
496 if (not prev.contains(end))
499 return {dist_from_start, prev};
503template <
class NodeType,
class Cost,
class CounterType,
class H>
504 requires Hashable<NodeType> and std::is_arithmetic_v<Cost>
512 const auto [from, to, cost] = edge;
513 this->
graph[from].insert({to, cost});
514 this->
graph[to].insert({from, cost});
520 -> std::optional<edge_error>
override {
521 const auto &[from, to, old_cost] = edge;
523 decltype(edge) forward_edge = {from, to, old_cost};
524 decltype(edge) backward_edge = {to, from, old_cost};
531 return dg::modifyEdge(backward_edge, new_cost);
535 -> std::vector<
CounterEdge<CounterType, Cost>>
override {
536 decltype(
edges()) result;
537 std::unordered_set<CounterType> processed;
538 for (
auto &[node, neighbors_info] : this->
graph) {
539 for (
auto &[to_neighbor, cost] : neighbors_info) {
540 if (node != to_neighbor && processed.contains(node))
542 result.push_back({node, to_neighbor, cost});
544 processed.insert(node);
549 -> std::vector<std::vector<CounterType>>
override {
553 -> std::vector<CounterEdge<CounterType, Cost>> {
557 std::priority_queue<CounterEdge<CounterType, Cost>,
558 std::vector<CounterEdge<CounterType, Cost>>,
559 decltype([](
auto a,
auto b) {
560 return std::get<2>(a) > std::get<2>(b);
563 pq.push_range(
edges);
566 while (!pq.empty()) {
567 auto [from, to, cost] = pq.top();
570 conn.
unite(from, to);
571 mst.push_back({from, to, cost});
584 std::unordered_map<CounterType, uint32_t> rank;
587 CounterType find(CounterType a) {
588 if (uf.find(a) == uf.end())
598 return this->find(a) == this->find(b);
603 void unite(CounterType a, CounterType b) {
604 auto ra = this->find(a);
605 auto rb = this->find(b);
609 if (rank[ra] > rank[rb])
613 if (rank[ra] == rank[rb])
614 rank[rb] = rank[rb] + 1;
INFO: Connectivity is just glorified union find, this is from DPV book.
Definition lean_graph.h:582
bool is_connected(CounterType a, CounterType b)
Definition lean_graph.h:597
void unite(CounterType a, CounterType b)
INFO: Unite (Union) a with b.
Definition lean_graph.h:603
INFO: A counter class.
Definition lean_graph.h:113
Counter(CounterType start_from)
Definition lean_graph.h:118
CounterType get_counter() const
Definition lean_graph.h:129
CounterType get_counter(const Aspect &aspect)
Definition lean_graph.h:124
bool counter_exceeds(CounterType ct) const
Definition lean_graph.h:123
bool exist(const Aspect &aspect) const
Definition lean_graph.h:119
Definition lean_graph.h:461
virtual auto singular_shortest_path(CounterType start, CounterType end) const -> std::pair< std::unordered_map< CounterType, Cost >, std::unordered_map< CounterType, CounterType > > override
Definition lean_graph.h:470
auto topo_sort() const -> std::vector< CounterType >
Definition lean_graph.h:464
Definition lean_graph.h:137
auto registerNode(const NodeType &node) -> CounterType
Definition lean_graph.h:226
CounterType num_edge
Definition lean_graph.h:144
virtual auto modifyEdge(CounterEdge< CounterType, Cost > edge, Cost new_cost) -> std::optional< edge_error >
Definition lean_graph.h:240
auto scc() -> std::vector< DiGraph > const
INFO: Strongly connected components (SCC)
Counter< NodeType, CounterType, H > node_counter
Definition lean_graph.h:143
auto existEdge(CounterEdge< CounterType, Cost > edge) const -> bool
Definition lean_graph.h:255
auto explore_dfs_protected(CounterType from, std::optional< std::reference_wrapper< std::unordered_set< CounterType > > > pre_visited=std::nullopt) const -> std::vector< CounterType >
Definition lean_graph.h:146
auto existCounterNode(CounterType node) const -> bool
Definition lean_graph.h:284
auto explore_bfs(CounterType from) const -> std::vector< CounterType >
Definition lean_graph.h:344
virtual auto registerEdge(CounterEdge< CounterType, Cost > edge) -> void
Definition lean_graph.h:232
friend class EdgeIte
Definition lean_graph.h:452
virtual auto edges() const -> std::vector< CounterEdge< CounterType, Cost > >
Definition lean_graph.h:288
auto bfs() const -> std::vector< CounterType >
Definition lean_graph.h:319
virtual auto cycles() const -> std::vector< std::vector< CounterType > >
INFO: Johnson algorithm.
Definition lean_graph.h:351
auto existBlankEdge(CounterBlankEdge< CounterType > edge) const -> bool
Definition lean_graph.h:265
virtual auto singular_shortest_path(CounterType start, CounterType end) const -> std::pair< std::unordered_map< CounterType, Cost >, std::unordered_map< CounterType, CounterType > >
Definition lean_graph.h:362
auto explore_bfs_protected(CounterType from, std::optional< std::reference_wrapper< std::unordered_set< CounterType > > > pre_visited=std::nullopt) const -> std::vector< CounterType >
Definition lean_graph.h:186
auto explore_dfs(CounterType from) const -> std::vector< CounterType >
Definition lean_graph.h:335
auto existBlankEdge(CounterEdge< CounterType, Cost > edge) const -> bool
Definition lean_graph.h:280
auto dfs() const -> std::vector< CounterType >
Definition lean_graph.h:302
CounterType num_node
Definition lean_graph.h:144
std::unordered_map< CounterType, std::set< CounterHalfEdge< CounterType, Cost > > > graph
Definition lean_graph.h:141
auto bellman_ford(CounterType start) const -> std::pair< std::unordered_map< CounterType, Cost >, std::unordered_map< CounterType, CounterType > > const
Definition lean_graph.h:403
Definition lean_graph.h:132
Definition lean_graph.h:505
auto registerEdge(CounterEdge< CounterType, Cost > edge) -> void override
Definition lean_graph.h:508
auto modifyEdge(CounterEdge< CounterType, Cost > edge, Cost new_cost) -> std::optional< edge_error > override
Definition lean_graph.h:518
auto edges() const -> std::vector< CounterEdge< CounterType, Cost > > override
Definition lean_graph.h:534
auto cycles() const -> std::vector< std::vector< CounterType > > override
INFO: Johnson algorithm.
Definition lean_graph.h:548
auto mst_kruskal() -> std::vector< CounterEdge< CounterType, Cost > >
Definition lean_graph.h:552
Definition lean_graph.h:24
Definition lean_graph.h:17
VisitOrder
Definition lean_graph.h:66
@ post
Definition lean_graph.h:66
@ pre
Definition lean_graph.h:66
std::tuple< CounterType, Cost > CounterHalfEdge
Definition lean_graph.h:74
edge_error
Definition lean_graph.h:65
@ not_exist
Definition lean_graph.h:65
std::tuple< CounterType, CounterType > CounterBlankEdge
Definition lean_graph.h:72
std::tuple< CounterType, CounterType, Cost > CounterEdge
Definition lean_graph.h:70
std::unordered_map< NodeType, CounterType > DefaultHashMap
Definition lean_graph.h:30
node_error
Definition lean_graph.h:64
@ duplicate
Definition lean_graph.h:64
@ general_error
Definition lean_graph.h:64
@ not_exist
Definition lean_graph.h:64
std::tuple< CounterType, CounterType, Cost > Edge
Definition lean_graph.h:77