Clone a Directed Acyclic Graph

27 Jan, 2022
A directed acyclic graph (DAG) is a graph which doesn’t contain a cycle and has directed edges. We are given a DAG, we need to clone it, i.e., create another graph that has copy of its vertices and edges connecting them.
Examples:  
Input :
 
0 - - - > 1 - - - -> 4
|        /  \        ^   
|       /    \       |  
|      /      \      |
|     /        \     |  
|    /          \    |
|   /            \   |
v  v              v  |
2 - - - - - - - - -> 3


Output : Printing the output of the cloned graph gives: 
0-1
1-2
2-3
3-4
1-3
1-4
0-2
To clone a DAG without storing the graph itself within a hash (or dictionary in Python). To clone, it we basically do a depth-first traversal of the nodes, taking original node’s value and initializing new neighboring nodes with the same value, recursively doing, till the original graph is fully traversed. Below is the recursive approach to cloning a DAG (in Python). We make use of dynamic lists in Python, append operation to this list happens in constant time, hence, fast and efficient initialization of the graph.
C++14
Java
Python3
// C++ program to clone a directed acyclic graph.#include <bits/stdc++.h>using namespace std; // Class to create a new graph nodeclass Node{    public:        int key;        vector<Node *> adj;                 // key is the value of the node        // adj will be holding a dynamic        // list of all Node type neighboring        // nodes        Node(int key)        {            this->key = key;        }}; // Function to print a graph,// depth-wise, recursivelyvoid printGraph(Node *startNode,                vector<bool> &visited){         // Visit only those nodes who have any    // neighboring nodes to be traversed    if (!startNode->adj.empty())    {                 // Loop through the neighboring nodes        // of this node. If source node not already        // visited, print edge from source to        // neighboring nodes. After visiting all        // neighbors of source node, mark its visited        // flag to true        for(auto i : startNode->adj)        {            if (!visited[startNode->key])            {                cout << "edge " << startNode                     << "-" << i                     << ":" << startNode->key                     << "-" << i->key                     << endl;                if (!visited[i->key])                {                    printGraph(i, visited);                    visited[i->key] = true;                }            }        }    }} // Function to clone a graph. To do this, we// start reading the original graph depth-wise,// recursively. If we encounter an unvisited// node in original graph, we initialize a// new instance of Node for cloned graph with// key of original nodeNode *cloneGraph(Node *oldSource,                 Node *newSource,                 vector<bool> &visited){    Node *clone = NULL;         if (!visited[oldSource->key] &&        !oldSource->adj.empty())    {        for(auto old : oldSource->adj)        {                         // Below check is for backtracking, so new            // nodes don't get initialized everytime            if (clone == NULL ||               (clone != NULL &&               clone->key != old->key))                clone = new Node(old->key);                             newSource->adj.push_back(clone);            cloneGraph(old, clone, visited);                         // Once, all neighbors for that particular node            // are created in cloned graph, code backtracks            // and exits from that node, mark the node as            // visited in original graph, and traverse the            // next unvisited            visited[old->key] = true;        }    }    return newSource;} // Driver Codeint main(){    Node *n0 = new Node(0);    Node *n1 = new Node(1);    Node *n2 = new Node(2);    Node *n3 = new Node(3);    Node *n4 = new Node(4);         n0->adj.push_back(n1);    n0->adj.push_back(n2);    n1->adj.push_back(n2);    n1->adj.push_back(n3);    n1->adj.push_back(n4);    n2->adj.push_back(n3);    n3->adj.push_back(n4);         // Flag to check if a node is already visited.    // Stops indefinite looping during recursion    vector<bool> visited(5, false);    cout << "Graph Before Cloning:-\n";    printGraph(n0, visited);    visited = { false, false, false, false, false };         cout << "\nGraph Before Starts:-\n";    Node *clonedGraphHead = cloneGraph(        n0, new Node(n0->key), visited);    cout << "Cloning Process Completes.\n";         visited = { false, false, false, false, false };    cout << "\nGraph After Cloning:-\n";    printGraph(clonedGraphHead, visited);         return 0;} // This code is contributed by sanjeev2552
// Java program to clone a directed acyclic graph.import java.util.*; class GFG{ // Class to create a new graph nodestatic class Node{    int key;    ArrayList<Node> adj = new ArrayList<Node>();         // key is the value of the node    // adj will be holding a dynamic    // list of all Node type neighboring    // nodes    Node(int key)    {        this.key = key;    }} // Function to print a graph,// depth-wise, recursivelystatic void printGraph(Node startNode,                       boolean[] visited){         // Visit only those nodes who have any    // neighboring nodes to be traversed    if (!startNode.adj.isEmpty())    {                 // Loop through the neighboring nodes        // of this node. If source node not already        // visited, print edge from source to        // neighboring nodes. After visiting all        // neighbors of source node, mark its visited        // flag to true        for(Node i : startNode.adj)        {            if (!visited[startNode.key])            {                System.out.println("edge " + startNode +                             "-" + i + ":" + startNode.key +                             "-" + i.key);                                 if (!visited[i.key])                {                    printGraph(i, visited);                    visited[i.key] = true;                }            }        }    }} // Function to clone a graph. To do this, we// start reading the original graph depth-wise,// recursively. If we encounter an unvisited// node in original graph, we initialize a// new instance of Node for cloned graph with// key of original nodestatic Node cloneGraph(Node oldSource,                       Node newSource,                       boolean[] visited){    Node clone = null;         if (!visited[oldSource.key] &&        !oldSource.adj.isEmpty())    {        for(Node old : oldSource.adj)        {                         // Below check is for backtracking, so new            // nodes don't get initialized everytime            if (clone == null ||               (clone != null &&                clone.key != old.key))                clone = new Node(old.key);                             newSource.adj.add(clone);            cloneGraph(old, clone, visited);                         // Once, all neighbors for that particular node            // are created in cloned graph, code backtracks            // and exits from that node, mark the node as            // visited in original graph, and traverse the            // next unvisited            visited[old.key] = true;        }    }    return newSource;} // Driver Codepublic static void main(String[] args){    Node n0 = new Node(0);    Node n1 = new Node(1);    Node n2 = new Node(2);    Node n3 = new Node(3);    Node n4 = new Node(4);         n0.adj.add(n1);    n0.adj.add(n2);    n1.adj.add(n2);    n1.adj.add(n3);    n1.adj.add(n4);    n2.adj.add(n3);    n3.adj.add(n4);         // Flag to check if a node is already visited.    // Stops indefinite looping during recursion    boolean visited[] = new boolean[5];    System.out.println("Graph Before Cloning:-");    printGraph(n0, visited);    Arrays.fill(visited, false);         System.out.println("\nCloning Process Starts");    Node clonedGraphHead = cloneGraph(        n0, new Node(n0.key), visited);    System.out.println("Cloning Process Completes.");         Arrays.fill(visited, false);    System.out.println("\nGraph After Cloning:-");    printGraph(clonedGraphHead, visited);}} // This code is contributed by adityapande88
# Python program to clone a directed acyclic graph. # Class to create a new graph nodeclass Node():     # key is the value of the node    # adj will be holding a dynamic    # list of all Node type neighboring    # nodes    def __init__(self, key = None, adj = None):        self.key = key        self.adj = adj # Function to print a graph, depth-wise, recursivelydef printGraph(startNode, visited):     # Visit only those nodes who have any    # neighboring nodes to be traversed    if startNode.adj is not None:         # Loop through the neighboring nodes        # of this node. If source node not already        # visited, print edge from source to        # neighboring nodes. After visiting all        # neighbors of source node, mark its visited        # flag to true        for i in startNode.adj:            if visited[startNode.key] == False :                print("edge %s-%s:%s-%s"%(hex(id(startNode)), hex(id(i)), startNode.key, i.key))                if visited[i.key] == False:                    printGraph(i, visited)                    visited[i.key] = True # Function to clone a graph. To do this, we start# reading the original graph depth-wise, recursively# If we encounter an unvisited node in original graph,# we initialize a new instance of Node for# cloned graph with key of original nodedef cloneGraph(oldSource, newSource, visited):    clone = None    if visited[oldSource.key] is False and oldSource.adj is not None:        for old in oldSource.adj:             # Below check is for backtracking, so new            # nodes don't get initialized everytime            if clone is None or(clone is not None and clone.key != old.key):                clone = Node(old.key, [])            newSource.adj.append(clone)            cloneGraph(old, clone, visited)             # Once, all neighbors for that particular node            # are created in cloned graph, code backtracks            # and exits from that node, mark the node as            # visited in original graph, and traverse the            # next unvisited            visited[old.key] = True    return newSource # Creating DAG to be cloned# In Python, we can do as many assignments of# variables in one single line by using commasn0, n1, n2 = Node(0, []), Node(1, []), Node(2, [])n3, n4 = Node(3, []), Node(4)n0.adj.append(n1)n0.adj.append(n2)n1.adj.append(n2)n1.adj.append(n3)n1.adj.append(n4)n2.adj.append(n3)n3.adj.append(n4) # flag to check if a node is already visited.# Stops indefinite looping during recursionvisited = [False]* (5)print("Graph Before Cloning:-")printGraph(n0, visited) visited = [False]* (5)print("\nCloning Process Starts")clonedGraphHead = cloneGraph(n0, Node(n0.key, []), visited)print("Cloning Process Completes.") visited = [False]*(5)print("\nGraph After Cloning:-")printGraph(clonedGraphHead, visited)
Output: 
Graph Before Cloning:-
edge 0x7fa03dd43878-0x7fa03dd43908:0-1
edge 0x7fa03dd43908-0x7fa03dd43950:1-2
edge 0x7fa03dd43950-0x7fa03dd43998:2-3
edge 0x7fa03dd43998-0x7fa03dd439e0:3-4
edge 0x7fa03dd43908-0x7fa03dd43998:1-3
edge 0x7fa03dd43908-0x7fa03dd439e0:1-4
edge 0x7fa03dd43878-0x7fa03dd43950:0-2

Cloning Process Starts
Cloning Process Completes.

Graph After Cloning:-
edge 0x7fa03dd43a28-0x7fa03dd43a70:0-1
edge 0x7fa03dd43a70-0x7fa03dd43ab8:1-2
edge 0x7fa03dd43ab8-0x7fa03dd43b00:2-3
edge 0x7fa03dd43b00-0x7fa03dd43b48:3-4
edge 0x7fa03dd43a70-0x7fa03dd43b90:1-3
edge 0x7fa03dd43a70-0x7fa03dd43bd8:1-4
edge 0x7fa03dd43a28-0x7fa03dd43c20:0-2
Creating the DAG by appending adjacent edges to the vertex happens in O(1) time. Cloning of the graph takes O(E+V) time. 
This article is contributed by Raveena. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above. 
 
sanjeev2552
adityapande88
surinderdawra388
amartyaghoshgfg
DFS
graph-cycle
Graph
DFS
Graph
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.