mirror of
https://gitlab.com/mfocko/Codeforces.git
synced 2024-12-22 06:01:20 +01:00
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:
parent
c0598833ea
commit
0108966775
1 changed files with 39 additions and 14 deletions
|
@ -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>) {
|
||||
let mut is_final = vec![false; costs.len()];
|
||||
let mut marks = vec![Mark::None; costs.len()];
|
||||
|
||||
// set cost of unlimited
|
||||
for i in unlimited {
|
||||
costs[i - 1] = 0;
|
||||
is_final[i - 1] = true;
|
||||
marks[i - 1] = Mark::Permanent;
|
||||
}
|
||||
|
||||
// set cost of inconstructible
|
||||
let mut q: HashSet<usize> = HashSet::new();
|
||||
for (i, way) in ways.iter().enumerate() {
|
||||
if way.estimated_cost(costs) == u64::MAX {
|
||||
is_final[i] = true;
|
||||
} else {
|
||||
q.insert(i);
|
||||
marks[i] = Mark::Permanent;
|
||||
}
|
||||
}
|
||||
|
||||
while let Some(i) = q
|
||||
.iter()
|
||||
.filter(|i| !is_final[**i])
|
||||
.min_by_key(|i| ways[**i].estimated_cost(costs))
|
||||
.map(|i| *i)
|
||||
{
|
||||
// do toposort to find the ideal order
|
||||
for i in toposort(&ways, &mut marks) {
|
||||
costs[i] = min(costs[i], ways[i].estimated_cost(costs));
|
||||
is_final[i] = true;
|
||||
q.remove(&i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue