1851(E,rs): finish “Nastya and Potions”

* use toposort instead of a queue

Signed-off-by: Matej Focko <me@mfocko.xyz>
This commit is contained in:
Matej Focko 2023-07-30 19:36:04 +02:00
parent c0598833ea
commit 0108966775
Signed by: mfocko
GPG key ID: 7C47D46246790496

View file

@ -25,34 +25,59 @@ impl Way {
} }
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Mark {
None,
Temporary,
Permanent,
}
fn toposort(ways: &[Way], marks: &mut Vec<Mark>) -> Vec<usize> {
fn visit(ways: &[Way], marks: &mut Vec<Mark>, ordering: &mut Vec<usize>, u: usize) {
match marks[u] {
Mark::None => {
marks[u] = Mark::Temporary;
for v in &ways[u].required {
visit(ways, marks, ordering, v - 1);
}
marks[u] = Mark::Permanent;
ordering.push(u);
}
Mark::Temporary => unreachable!("no loops should be present"),
Mark::Permanent => { /* no-op */ }
}
}
let mut ordering = vec![];
for i in 0..marks.len() {
visit(ways, marks, &mut ordering, i);
}
ordering
}
fn find_costs(costs: &mut Vec<u64>, unlimited: Vec<usize>, ways: Vec<Way>) { fn find_costs(costs: &mut Vec<u64>, unlimited: Vec<usize>, ways: Vec<Way>) {
let mut is_final = vec![false; costs.len()]; let mut marks = vec![Mark::None; costs.len()];
// set cost of unlimited // set cost of unlimited
for i in unlimited { for i in unlimited {
costs[i - 1] = 0; costs[i - 1] = 0;
is_final[i - 1] = true; marks[i - 1] = Mark::Permanent;
} }
// set cost of inconstructible // set cost of inconstructible
let mut q: HashSet<usize> = HashSet::new();
for (i, way) in ways.iter().enumerate() { for (i, way) in ways.iter().enumerate() {
if way.estimated_cost(costs) == u64::MAX { if way.estimated_cost(costs) == u64::MAX {
is_final[i] = true; marks[i] = Mark::Permanent;
} else {
q.insert(i);
} }
} }
while let Some(i) = q // do toposort to find the ideal order
.iter() for i in toposort(&ways, &mut marks) {
.filter(|i| !is_final[**i])
.min_by_key(|i| ways[**i].estimated_cost(costs))
.map(|i| *i)
{
costs[i] = min(costs[i], ways[i].estimated_cost(costs)); costs[i] = min(costs[i], ways[i].estimated_cost(costs));
is_final[i] = true;
q.remove(&i);
} }
} }