public Graph getMinBranching(Node pRootNode, Graph pGraph) {
        Graph reverse = pGraph.getReversedList();
        // remove all edges entering the root
        if (reverse.getAdjacent(pRootNode) != null) {
            reverse.getAdjacent(pRootNode).clear();
        }
        Graph outEdges = new Graph();
        // for each node, select the edge entering it with smallest weight
        for (Node node : reverse.getSourceNodeSet()) {
            ArrayList<Edge> inEdges = reverse.getAdjacent(node);
            if (inEdges.isEmpty()) {
                continue;
            }
            Edge minEdge = inEdges.get(0);
            for (Edge edge : inEdges) {
                if (edge.getWeight() < minEdge.getWeight()) {
                    minEdge = edge;
                }
            }
           outEdges.addEdge(minEdge.getDestination(), minEdge.getSource(), minEdge.getWeight());
        }

        // detect cycles
        ArrayList<ArrayList<Node>> cycles = new ArrayList<>();
        cycle = new ArrayList<>();
        getCycle(pRootNode, outEdges);
        cycles.add(cycle);
        for (Node node : outEdges.getSourceNodeSet()) {
            if (!node.isVisited()) {
                cycle = new ArrayList<>();
                getCycle(node, outEdges);
                cycles.add(cycle);
            }
        }

        // for each cycle formed, modify the path to merge it into another part of the graph
        Graph outEdgesReverse = outEdges.getReversedList();

        for (int nodeIndex = 0; nodeIndex < cycles.size(); nodeIndex++) {
            if (cycles.get(nodeIndex).contains(pRootNode)) {
                continue;
            }
            mergeCycles(cycles.get(nodeIndex), pGraph, reverse, outEdges, outEdgesReverse);
        }
        return outEdges;
    }