# Clone a Directed Acyclic Graph

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
```

## Recommended: Please try your approach on {IDE} first, before moving on to the solution.

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.

 `# Python program to clon a directed acyclic graph. ` ` `  `# Class to create a new graph node ` `class` `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, recursively ` `def` `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 node ` `def` `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 commas ` `n0, 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 recursion ` `visited ``=` `[``False``]``*` `(``5``) ` `print``(``"Graph Before Cloning:-"``) ` `printGraph(n0, visited) ` ` `  `visited ``=` `[``False``]``*` `(``5``) ` `print``(````" Cloning Process Starts"````) ` `clonedGraphHead ``=` `cloneGraph(n0, Node(n0.key, []), visited) ` `print``(``"Cloning Process Completes."``) ` ` `  `visited ``=` `[``False``]``*``(``5``) ` `print``(````" Graph 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.

## tags:

Graph DFS graph-cycle DFS Graph