///|
// Iterative Kosaraju condensation keeps deep and cyclic scopes off the call stack.
fn ranks(
members : ArrayView[Int32],
links : ArrayView[(Int32, Int32)],
budget : Budget,
) -> Map[Int32, Int32] {
let outgoing : Map[Int32, Array[Int32]] = Map([])
let incoming : Map[Int32, Array[Int32]] = Map([])
for (a, b) in links {
if !budget.charge(1) {
return Map([])
}
match outgoing.get(a) {
Some(values) => values.push(b)
None => outgoing[a] = [b]
}
match incoming.get(b) {
Some(values) => values.push(a)
None => incoming[b] = [a]
}
}
let seen = Map([])
let order = []
for start in members {
let stack = [(start, false)]
while stack.pop() is Some((node, leave)) {
if !budget.charge(1) {
return Map([])
}
if leave {
order.push(node)
continue
}
if seen.contains(node) {
continue
}
seen[node] = true
stack.push((node, true))
let neighbors = outgoing.get(node).unwrap_or([])
for i in 0.. [])
let indegree = Array::make(count.length(), 0)
let rank = Array::make(count.length(), 0)
for (a, b) in links {
if !budget.charge(1) {
return Map([])
}
let a = components[a]
let b = components[b]
if a != b && !edges.contains((a, b)) {
edges[(a, b)] = true
next[a].push(b)
indegree[b] += 1
}
}
let queue = []
for i in 0..