///|
// Iterative Kosaraju condensation keeps deep and cyclic scopes off the call stack.
fn ranks(members : ArrayView[Int], links : ArrayView[(Int,Int)], budget : Budget) -> Map[Int,Int] {
let outgoing : Map[Int,Array[Int]]=Map([]); let incoming : Map[Int,Array[Int]]=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..