use std::collections::HashMap; use std::collections::HashSet; pub fn reverse_graph( rel: &[(usize,usize)], rel_rev: & mut [(usize,usize)] ) { for (i,v) in rel.iter().enumerate() { rel_rev[i] = ( v.1, v.0 ); } } pub fn adj_list( rel: &[(usize,usize)] ) -> HashMap< usize, HashSet< usize > > { let mut rev_adj = HashMap::new(); for i in rel.iter() { let exists = rev_adj.contains_key(&i.0); if !exists { let mut new_set = HashSet::new(); new_set.insert( i.1 ); rev_adj.insert( i.0, new_set ); } else { match rev_adj.get_mut( &i.0 ) { Some(x) => { x.insert( i.1 ); }, None => { // panic!("unexpected result"); }, }; } } rev_adj } pub fn visit_post_order( num_nodes: usize, adj: & HashMap< usize, HashSet< usize > > ) -> Vec { let mut visited = vec![ false; num_nodes ]; let mut queue = vec![]; let mut visit_order = vec![]; for i in 0..num_nodes { if visited[ i ] == false { visited[ i ] = true; queue.push(i); } loop { let n = match queue.last() { Some(n) => { *n }, _ => { break; }, }; let mut found = false; if let Some( y ) = adj.get( &n ) { for k in y.iter() { if visited[*k ] == false { visited[*k ] = true; queue.push(*k); found = true; } } }; if found { continue; } visit_order.push( n ); queue.pop(); } } visit_order } pub fn compute( num_nodes: usize, rel: &[(usize,usize)] ) -> Vec< usize > { let mut out = vec![ 0; num_nodes ]; //computes strongly connected components using Kosaraju's algorithm let adj = adj_list( &rel[..] ); // println!( "adj: {:?}", adj ); //get reverse of the post order of the dfs let visit_order = { let mut a = visit_post_order( num_nodes, &adj ); a.reverse(); a }; // println!( "visit order: {:?}", visit_order ); //get transpose graph let mut rel_rev = vec![ (0usize, 0usize); rel.len() ]; reverse_graph( rel, & mut rel_rev[..] ); // println!( "reverse rel: {:?}", rel_rev ); let rev_adj = adj_list( &rel_rev[..] ); // println!( "reverse adj lists: {:?}", rev_adj ); //compute the ssc components let mut component_id = 0; let mut node_to_component = HashMap::new(); for i in visit_order.iter() { // println!( "visit: {}", i ); if !node_to_component.contains_key(i) { component_id += 1; let mut queue = vec![i]; loop { let n = match queue.last() { Some(n) => { *n }, _ => { break; }, }; let mut found = false; if !node_to_component.contains_key( n ) { node_to_component.insert( *n, component_id ); found = true; if let Some( y ) = rev_adj.get( n ) { for k in y.iter() { queue.push(k); } }; } if !found { queue.pop(); } } } } for (k, v) in node_to_component { out[ k ] = v; } out }