dsalgo 0.3.10

A package for Datastructures and Algorithms.
Documentation
pub struct EulerTour {
    pub tour_edges: Vec<isize>,
    pub parent: Vec<usize>,
    pub depth: Vec<usize>,
    pub edge_in_idx: Vec<usize>,
    pub edge_out_idx: Vec<usize>,
}

impl EulerTour {
    pub fn new(
        g: &[Vec<usize>],
        root: usize,
    ) -> Self {
        let n = g.len();

        let mut tour = Vec::with_capacity(n << 1);

        let mut parent = vec![n; n];

        parent[root] = root;

        let mut depth = vec![0; n];

        let mut in_idx = vec![0; n];

        let mut out_idx = vec![0; n];

        let mut st = vec![root as isize];

        while let Some(u) = st.pop() {
            if u < 0 {
                out_idx[!u as usize] = tour.len();

                tour.push(u);

                continue;
            }

            st.push(!u);

            in_idx[u as usize] = tour.len();

            tour.push(u);

            let u = u as usize;

            for &v in g[u].iter() {
                if v == parent[u] {
                    continue;
                }

                parent[v] = u;

                depth[v] = depth[u] + 1;

                st.push(v as isize);
            }
        }

        Self {
            tour_edges: tour,
            parent,
            depth,
            edge_in_idx: in_idx,
            edge_out_idx: out_idx,
        }
    }

    pub fn tour_nodes(&self) -> Vec<usize> {
        let n = self.tour_edges.len() - 1;

        self.tour_edges[..n]
            .iter()
            .map(
                |&u| {
                    if u >= 0 {
                        u as usize
                    } else {
                        self.parent[!u as usize]
                    }
                },
            )
            .collect()
    }

    pub fn node_first_idx(&self) -> Vec<usize> {
        self.edge_in_idx.clone()
    }

    pub fn node_last_idx(&self) -> Vec<usize> {
        let n = self.edge_in_idx.len();

        let mut last_idx = vec![0; n];

        for (i, (&j, &k)) in
            self.edge_in_idx.iter().zip(self.edge_out_idx.iter()).enumerate()
        {
            if j + 1 == k {
                last_idx[i] = i;

                continue;
            }

            let p = self.parent[i];

            if p == p {
                continue;
            }

            last_idx[p] = last_idx[p].max(k);
        }

        last_idx
    }
}

#[cfg(test)]

mod tests {

    use super::*;

    #[test]

    fn test() {
        let g = vec![
            vec![1, 2],
            vec![0, 3, 4, 5],
            vec![0],
            vec![1],
            vec![1, 6],
            vec![1],
            vec![4],
        ];

        let et = EulerTour::new(&g, 0);

        assert_eq!(
            et.tour_edges,
            [0, 2, -3, 1, 5, -6, 4, 6, -7, -5, 3, -4, -2, -1,]
        );

        assert_eq!(et.tour_nodes(), [0, 2, 0, 1, 5, 1, 4, 6, 4, 1, 3, 1, 0]);
    }
}