public Map<Integer, GraphNode> clone(GraphNode source, Map<Integer, GraphNode> cloned) {
       // try DFS form source
        if(source == null) {
            return null;
        }
        // if cloned graph does not contain the node
        if(!cloned.containsKey(new Integer(source.label))) {
            // create by copying the souce node data
            GraphNode newNode = new GraphNode(source.label, new ArrayList<GraphNode>());
            cloned.put(new Integer(source.label), newNode);
        }

        //iterate through all the neighbours
        if(source.neighbours.size() > 0) {
            for(GraphNode neighbour : source.neighbours) {
                // if neighbour is not present in the graph
                if(!cloned.containsKey(new Integer(neighbour.label))) {
                    // create the neighbour by copying the content of neighbour
                    cloned.put(new Integer(neighbour.label), new GraphNode(neighbour.label, new ArrayList<GraphNode>()));
                }
                // if cloned source does not contain neighbour as one of its neighbour. It saves us from cyclic dependencies
                if(!cloned.get(new Integer(source.label)).neighbours.contains(cloned.get(new Integer(neighbour.label)))) {
                    // add the cloned neighbour to the neighbour list
                    cloned.get(new Integer(source.label)).neighbours.add(cloned.get(new Integer(neighbour.label)));
                    // recurse by making neghbour as source
                    cloned = clone(neighbour, cloned);
                }

            }
        }


        return cloned;

    }