Skip to content

Commit

Permalink
2023 graph: allow multiple sources in tarjan_scc()
Browse files Browse the repository at this point in the history
  • Loading branch information
yut23 committed Feb 21, 2024
1 parent 2875b4d commit 56c3ebc
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 30 deletions.
31 changes: 16 additions & 15 deletions 2023/src/day20.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,22 @@
#define DAY20_HPP_QRITMDTC

#include "graph_traversal.hpp"
#include "lib.hpp" // for DEBUG
#include <algorithm> // for all_of, transform, lower_bound, sort
#include <cassert> // for assert
#include <cstddef> // for size_t
#include <iostream> // for istream, ostream, cerr, cout
#include <iterator> // for back_inserter, distance
#include <memory> // for unique_ptr, make_unique
#include <numeric> // for lcm
#include <queue> // for queue
#include <set> // for set (tarjan_scc)
#include <sstream> // for istringstream
#include <string> // for string, getline
#include <unordered_map> // for unordered_map
#include <utility> // for move, forward
#include <vector> // for vector
#include "lib.hpp" // for DEBUG
#include <algorithm> // for all_of, transform, lower_bound, sort
#include <cassert> // for assert
#include <cstddef> // for size_t
#include <initializer_list> // for initializer_list (single-source tarjan_scc)
#include <iostream> // for istream, ostream, cerr, cout
#include <iterator> // for back_inserter, distance
#include <memory> // for unique_ptr, make_unique
#include <numeric> // for lcm
#include <queue> // for queue
#include <set> // for set (tarjan_scc)
#include <sstream> // for istringstream
#include <string> // for string, getline
#include <unordered_map> // for unordered_map
#include <utility> // for move, forward
#include <vector> // for vector
// IWYU pragma: no_include <functional> // for hash (unordered_map)

namespace aoc::day20 {
Expand Down
34 changes: 25 additions & 9 deletions 2023/src/graph_traversal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@
#include <cassert> // for assert
#include <concepts> // for same_as, integral
#include <functional> // for function, greater
#include <map> // for map
#include <queue> // for priority_queue
#include <set> // for set
#include <stack> // for stack
#include <stdexcept> // for invalid_argument
#include <tuple> // for tuple
#include <initializer_list> // for initializer_list
#include <map> // for map
#include <queue> // for priority_queue
#include <set> // for set
#include <stack> // for stack
#include <stdexcept> // for invalid_argument
#include <tuple> // for tuple
#include <type_traits> // for conditional_t, invoke_result_t // IWYU pragma: export
#include <unordered_map> // for unordered_map
#include <unordered_set> // for unordered_set
Expand Down Expand Up @@ -295,9 +296,11 @@ struct tarjan_entry {
* Components are returned in topological order, along with a set of the
* directed edges between the components.
*/
template <class Key, detail::GetNeighbors<Key> GetNeighbors>
template <class Key,
util::concepts::any_iterable_collection<Key> SourceCollection,
detail::GetNeighbors<Key> GetNeighbors>
std::pair<std::vector<std::vector<Key>>, std::set<std::pair<int, int>>>
tarjan_scc(const Key &source, GetNeighbors &&get_neighbors) {
tarjan_scc(const SourceCollection &sources, GetNeighbors &&get_neighbors) {
int index = 0;
std::stack<Key> S{};
std::vector<std::vector<Key>> components{};
Expand Down Expand Up @@ -355,7 +358,11 @@ tarjan_scc(const Key &source, GetNeighbors &&get_neighbors) {
return v_entry;
};

strongconnect(source, strongconnect);
for (const auto &source : sources) {
if (!entries.contains(source)) {
strongconnect(source, strongconnect);
}
}

// check edges
if constexpr (aoc::DEBUG) {
Expand All @@ -382,6 +389,13 @@ tarjan_scc(const Key &source, GetNeighbors &&get_neighbors) {
return {std::move(components), std::move(reversed_links)};
}

template <class Key, detail::GetNeighbors<Key> GetNeighbors>
std::pair<std::vector<std::vector<Key>>, std::set<std::pair<int, int>>>
tarjan_scc(const Key &source, GetNeighbors &&get_neighbors) {
const std::initializer_list<Key> sources = {source};
return tarjan_scc<Key>(sources, get_neighbors);
}

/**
* Longest path algorithm for a DAG.
*/
Expand Down Expand Up @@ -699,6 +713,8 @@ void _lint_helper_template(
topo_sort(source, get_neighbors);

tarjan_scc(source, get_neighbors);
const std::vector<Key> sources{source, source};
tarjan_scc<Key>(sources, get_neighbors);

longest_path_dag(source, get_neighbors, get_distance, is_target);

Expand Down
13 changes: 7 additions & 6 deletions 2023/src/test00_graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@
#include "unit_test/unit_test.hpp"

#include "graph_traversal.hpp"
#include <algorithm> // for sort
#include <cstddef> // for size_t
#include <set> // for set
#include <unordered_map> // for unordered_map
#include <utility> // for pair
#include <vector> // for vector
#include <algorithm> // for sort
#include <cstddef> // for size_t
#include <initializer_list> // for initializer_list (single-source tarjan_scc)
#include <set> // for set
#include <unordered_map> // for unordered_map
#include <utility> // for pair
#include <vector> // for vector

namespace aoc::graph::test {

Expand Down

0 comments on commit 56c3ebc

Please sign in to comment.