mirror of
https://gitlab.com/mfocko/Codeforces.git
synced 2024-11-09 13:49:06 +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>) {
|
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue