pub fn cycles_and_cut_candidates<N: Clone + Hash + Eq, E: Clone>(
    graph: &Graph<N, E>,
) -> Vec<Cycle<N>> {
    petgraph::algo::tarjan_scc(graph)
        .into_iter()
        .filter(|cycle| cycle.len() > 1)
        .map(|nodes| {
            let mut subgraph = graph.clone();
            subgraph.retain_nodes(|_, node| nodes.contains(&node));
            let cuts = edges_to_break_cycle(&subgraph);
            Cycle { nodes, cuts }
        })
        .collect()
}
Given a graph will look for cycles and edge sets that will remove the cycle.

If any cycles are found they will be returned alongside a list of sets of
edges that if they are cut will result in the graph no longer having a
cycle.
We return (N, N) tuples instead of edge indexes as indexes are not stable
across removals so the indexes in the subgraph do not match the full graph.
crates/turborepo-graph-utils/src/lib.rs