static Set<Set<Integer>> computeStronglyConnectedComponents(
            final int numVertex, final List<List<Integer>> outEdges) {
        final Set<Set<Integer>> stronglyConnectedComponents = new HashSet<>();

        // a vertex will be added into this stack when it is visited for the first time
        final Deque<Integer> visitingStack = new ArrayDeque<>(numVertex);
        final boolean[] onVisitingStack = new boolean[numVertex];

        // stores the order that a vertex is visited for the first time, -1 indicates it is not
        // visited yet
        final int[] vertexIndices = new int[numVertex];
        Arrays.fill(vertexIndices, -1);

        final AtomicInteger indexCounter = new AtomicInteger(0);

        final int[] vertexLowLinks = new int[numVertex];

        for (int vertex = 0; vertex < numVertex; vertex++) {
            if (!isVisited(vertex, vertexIndices)) {
                dfs(
                        vertex,
                        outEdges,
                        vertexIndices,
                        vertexLowLinks,
                        visitingStack,
                        onVisitingStack,
                        indexCounter,
                        stronglyConnectedComponents);
            }
        }

        return stronglyConnectedComponents;
    }
@Test
    void testWithNoEdge() {
        final List<List<Integer>> edges =
                Arrays.asList(
                        Collections.emptyList(),
                        Collections.emptyList(),
                        Collections.emptyList(),
                        Collections.emptyList(),
                        Collections.emptyList());

        final Set<Set<Integer>> result = computeStronglyConnectedComponents(5, edges);

        final Set<Set<Integer>> expected = new HashSet<>();
        expected.add(Collections.singleton(0));
        expected.add(Collections.singleton(1));
        expected.add(Collections.singleton(2));
        expected.add(Collections.singleton(3));
        expected.add(Collections.singleton(4));

        assertThat(result).isEqualTo(expected);
    }