fewer lookups in kahn's algorithm
This commit is contained in:
parent
35e31bf67f
commit
48da2e2805
29
2019/14.cpp
29
2019/14.cpp
|
@ -45,27 +45,30 @@ auto Parse(std::istream & in) -> Recipes {
|
||||||
auto Topsort(Recipes const& recipes) -> std::vector<std::string>
|
auto Topsort(Recipes const& recipes) -> std::vector<std::string>
|
||||||
{
|
{
|
||||||
// Kahn's algorithm
|
// Kahn's algorithm
|
||||||
std::set<std::string> perm;
|
|
||||||
std::set<std::string> temp;
|
|
||||||
std::vector<std::string> result;
|
std::vector<std::string> result;
|
||||||
|
result.reserve(recipes.size());
|
||||||
|
|
||||||
auto visit_ = [&](auto& rec, std::string name) -> void {
|
std::map<std::string, bool> marks; // false temp, true done
|
||||||
if (!perm.contains(name)) {
|
auto const visit = [&](auto const& visit, auto const& name) -> void {
|
||||||
if (!temp.insert(name).second) throw std::runtime_error{"cyclic recipes"};
|
auto [mark_iterator, is_new] = marks.try_emplace(name, false);
|
||||||
if (recipes.contains(name)) {
|
auto& [_, is_done] = *mark_iterator;
|
||||||
for (auto && [_, c] : recipes.at(name).second) {
|
|
||||||
rec(rec, c);
|
if (is_new) {
|
||||||
|
auto const rit = recipes.find(name);
|
||||||
|
if (rit != recipes.end()) {
|
||||||
|
for (auto const& [_, c] : rit->second.second) {
|
||||||
|
visit(visit, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
temp.erase(name);
|
is_done = true;
|
||||||
perm.insert(name);
|
|
||||||
result.push_back(name);
|
result.push_back(name);
|
||||||
|
} else if (!is_done) {
|
||||||
|
throw std::runtime_error{"cyclic graph"};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
auto visit = [&](auto name) { visit_(visit_, name); };
|
|
||||||
|
|
||||||
for (auto && [k,_] : recipes) {
|
for (auto const& [c,_] : recipes) {
|
||||||
visit(k);
|
visit(visit, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::reverse(result.begin(), result.end());
|
std::reverse(result.begin(), result.end());
|
||||||
|
|
Loading…
Reference in New Issue
Block a user