Open in App
Not now

# Maximum edges that can be added to DAG so that it remains DAG

• Difficulty Level : Medium
• Last Updated : 28 Feb, 2023

A DAG is given to us, we need to find maximum number of edges that can be added to this DAG, after which new graph still remain a DAG that means the reformed graph should have maximal number of edges, adding even single edge will create a cycle in graph.

```The Output for above example should be following edges in any order.
4-2, 4-5, 4-3, 5-3, 5-1, 2-0, 2-1, 0-3, 0-1```

As shown in above example, we have added all the edges in one direction only to save ourselves from making a cycle. This is the trick to solve this question. We sort all our nodes in topological order and create edges from node to all nodes to the right if not there already.
How can we say that, it is not possible to add any more edge? the reason is we have added all possible edges from left to right and if we want to add more edge we need to make that from right to left, but adding edge from right to left we surely create a cycle because its counter part left to right edge is already been added to graph and creating cycle is not what we needed.
So solution proceeds as follows, we consider the nodes in topological order and if any edge is not there from left to right, we will create it.

Below is the solution, we have printed all the edges that can be added to given DAG without making any cycle.

## C++

 `// C++ program to find maximum edges after adding` `// which graph still remains a DAG` `#include ` `using` `namespace` `std;`   `class` `Graph {` `    ``int` `V; ``// No. of vertices`   `    ``// Pointer to a list containing adjacency list` `    ``list<``int``>* adj;`   `    ``// Vector to store indegree of vertices` `    ``vector<``int``> indegree;`   `    ``// function returns a topological sort` `    ``vector<``int``> topologicalSort();`   `public``:` `    ``Graph(``int` `V); ``// Constructor`   `    ``// function to add an edge to graph` `    ``void` `addEdge(``int` `v, ``int` `w);`   `    ``// Prints all edges that can be added without making any` `    ``// cycle` `    ``void` `maximumEdgeAddition();` `};`   `//  Constructor of graph` `Graph::Graph(``int` `V)` `{` `    ``this``->V = V;` `    ``adj = ``new` `list<``int``>[V];`   `    ``// Initialising all indegree with 0` `    ``for` `(``int` `i = 0; i < V; i++)` `        ``indegree.push_back(0);` `}`   `//  Utility function to add edge` `void` `Graph::addEdge(``int` `v, ``int` `w)` `{` `    ``adj[v].push_back(w); ``// Add w to v's list.`   `    ``// increasing inner degree of w by 1` `    ``indegree[w]++;` `}`   `//  Main function to print maximum edges that can be added` `vector<``int``> Graph::topologicalSort()` `{` `    ``vector<``int``> topological;` `    ``queue<``int``> q;`   `    ``//  In starting push all node with indegree 0` `    ``for` `(``int` `i = 0; i < V; i++)` `        ``if` `(indegree[i] == 0)` `            ``q.push(i);`   `    ``while` `(!q.empty()) {` `        ``int` `t = q.front();` `        ``q.pop();`   `        ``//  push the node into topological vector` `        ``topological.push_back(t);`   `        ``//  reducing indegree of adjacent vertices` `        ``for` `(list<``int``>::iterator j = adj[t].begin();` `             ``j != adj[t].end(); j++) {` `            ``indegree[*j]--;`   `            ``//  if indegree becomes 0, just push` `            ``// into queue` `            ``if` `(indegree[*j] == 0)` `                ``q.push(*j);` `        ``}` `    ``}` `    ``return` `topological;` `}`   `//  The function prints all edges that can be` `//  added without making any cycle` `//  It uses recursive topologicalSort()` `void` `Graph::maximumEdgeAddition()` `{` `    ``bool``* visited = ``new` `bool``[V];` `    ``vector<``int``> topo = topologicalSort();`   `    ``//  looping for all nodes` `    ``for` `(``int` `i = 0; i < topo.size(); i++) {` `        ``int` `t = topo[i];`   `        ``//  In below loop we mark the adjacent node of t` `        ``for` `(list<``int``>::iterator j = adj[t].begin();` `             ``j != adj[t].end(); j++)` `            ``visited[*j] = ``true``;`   `        ``//  In below loop unmarked nodes are printed` `        ``for` `(``int` `j = i + 1; j < topo.size(); j++) {` `            ``// if not marked, then we can make an edge` `            ``// between t and j` `            ``if` `(!visited[topo[j]])` `                ``cout << t << ``"-"` `<< topo[j] << ``" "``;`   `            ``visited[topo[j]] = ``false``;` `        ``}` `    ``}` `}`   `// Driver code to test above methods` `int` `main()` `{` `    ``// Create a graph given in the above diagram` `    ``Graph g(6);` `    ``g.addEdge(5, 2);` `    ``g.addEdge(5, 0);` `    ``g.addEdge(4, 0);` `    ``g.addEdge(4, 1);` `    ``g.addEdge(2, 3);` `    ``g.addEdge(3, 1);`   `    ``g.maximumEdgeAddition();` `    ``return` `0;` `}`

## Java

 `// Java program to find maximum edges after adding` `// which graph still remains a DAG` `import` `java.util.*;`   `public` `class` `Graph {`   `  ``int` `V;   ``// No. of vertices`   `  ``ArrayList> adj;  ``// adjacency list`   `  ``// array to store indegree of vertices` `  ``int``[] indegree;`   `  ``//  Constructor of graph` `  ``Graph(``int` `v)` `  ``{` `    ``this``.V = v;` `    ``indegree = ``new` `int``[V];` `    ``adj = ``new` `ArrayList<>(V);`   `    ``for``(``int` `i = ``0``; i < V; i++)` `    ``{` `      ``adj.add(``new` `ArrayList());` `      ``indegree[i] = ``0``;` `    ``}` `  ``}`   `  ``//  Utility function to add edge` `  ``public` `void` `addEdge(``int` `v,``int` `w) ` `  ``{` `    ``adj.get(v).add(w);``// Add w to v's list.`   `    ``// increasing inner degree of w by 1` `    ``indegree[w]++;` `  ``}`   `  ``//  Main function to print maximum edges that can be added` `  ``public` `List topologicalSort()  ` `  ``{`   `    ``List topological = ``new` `ArrayList<>(V); ` `    ``Queue q = ``new` `LinkedList<>();`   `    ``//  In starting push all node with indegree 0` `    ``for``(``int` `i = ``0``; i < V; i++)` `    ``{` `      ``if``(indegree[i] == ``0``)` `      ``{` `        ``q.add(i);` `      ``}` `    ``}`     `    ``while``(!q.isEmpty())` `    ``{` `      ``int` `t=q.poll();`   `      ``//  push the node into topological list` `      ``topological.add(t);`   `      ``//  reducing inDegree of adjacent vertical        ` `      ``for``(``int` `j: adj.get(t))` `      ``{` `        ``indegree[j]--;`   `        ``//  if inDegree becomes 0, just push` `        ``// into queue` `        ``if``(indegree[j] == ``0``)` `        ``{` `          ``q.add(j);` `        ``}` `      ``}`   `    ``}`   `    ``return` `topological;`   `  ``}`   `  ``//  The function prints all edges that can be` `  ``//  added without making any cycle` `  ``//  It uses recursive topologicalSort()` `  ``public` `void` `maximumEdgeAddition()` `  ``{` `    ``boolean``[] visited = ``new` `boolean``[V];` `    ``List topo=topologicalSort();`   `    ``//  looping for all nodes` `    ``for``(``int` `i = ``0``; i < topo.size(); i++)` `    ``{` `      ``int` `t = topo.get(i);`   `      ``//  In below loop we mark the adjacent node of t` `      ``for``( Iterator j = adj.get(t).listIterator();j.hasNext();)` `      ``{` `        ``visited[j.next()] = ``true``;` `      ``}`   `      ``for``(``int` `j = i + ``1``; j < topo.size(); j++)` `      ``{` `        ``// if not marked, then we can make an edge` `        ``// between t and j` `        ``if``(!visited[topo.get(j)])` `        ``{` `          ``System.out.print( t  + ``"-"` `+ topo.get(j) + ``" "``);` `        ``}`   `        ``visited[topo.get(j)] = ``false``;` `      ``}` `    ``}` `  ``}`   `  ``// Driver code to test above methods` `  ``public` `static` `void` `main(String[] args)` `  ``{     `   `    ``// Create a graph given in the above diagram` `    ``Graph g = ``new` `Graph(``6``);` `    ``g.addEdge(``5``, ``2``);` `    ``g.addEdge(``5``, ``0``);` `    ``g.addEdge(``4``, ``0``);` `    ``g.addEdge(``4``, ``1``);` `    ``g.addEdge(``2``, ``3``);` `    ``g.addEdge(``3``, ``1``);`   `    ``g.maximumEdgeAddition();` `    ``return` `;` `  ``}    ` `}`   `// This code is contributed by sameergupta22.`

## Python3

 `# Python3 program to find maximum` `# edges after adding which graph` `# still remains a DAG`     `class` `Graph:`   `    ``def` `__init__(``self``, V):`   `        ``# No. of vertices` `        ``self``.V ``=` `V`   `        ``# Pointer to a list containing` `        ``# adjacency list` `        ``self``.adj ``=` `[[] ``for` `i ``in` `range``(V)]`   `        ``# Vector to store indegree of vertices` `        ``self``.indegree ``=` `[``0` `for` `i ``in` `range``(V)]`   `    ``# Utility function to add edge` `    ``def` `addEdge(``self``, v, w):`   `         ``# Add w to v's list.` `        ``self``.adj[v].append(w)`   `        ``# Increasing inner degree of w by 1` `        ``self``.indegree[w] ``+``=` `1`   `    ``# Main function to print maximum` `    ``# edges that can be added` `    ``def` `topologicalSort(``self``):`   `        ``topological ``=` `[]` `        ``q ``=` `[]`   `        ``# In starting append all node` `        ``# with indegree 0` `        ``for` `i ``in` `range``(``self``.V):` `            ``if` `(``self``.indegree[i] ``=``=` `0``):` `                ``q.append(i)`   `        ``while` `(``len``(q) !``=` `0``):` `            ``t ``=` `q[``0``]` `            ``q.pop(``0``)`   `            ``# Append the node into topological` `            ``# vector` `            ``topological.append(t)`   `            ``# Reducing indegree of adjacent` `            ``# vertices` `            ``for` `j ``in` `self``.adj[t]:` `                ``self``.indegree[j] ``-``=` `1`   `                ``# If indegree becomes 0, just` `                ``# append into queue` `                ``if` `(``self``.indegree[j] ``=``=` `0``):` `                    ``q.append(j)`   `        ``return` `topological`   `    ``# The function prints all edges that` `    ``# can be added without making any cycle` `    ``# It uses recursive topologicalSort()` `    ``def` `maximumEdgeAddition(``self``):`   `        ``visited ``=` `[``False` `for` `i ``in` `range``(``self``.V)]`   `        ``topo ``=` `self``.topologicalSort()`   `        ``# Looping for all nodes` `        ``for` `i ``in` `range``(``len``(topo)):` `            ``t ``=` `topo[i]`   `            ``# In below loop we mark the` `            ``# adjacent node of t` `            ``for` `j ``in` `self``.adj[t]:` `                ``visited[j] ``=` `True`   `            ``# In below loop unmarked nodes` `            ``# are printed` `            ``for` `j ``in` `range``(i ``+` `1``, ``len``(topo)):`   `                ``# If not marked, then we can make` `                ``# an edge between t and j` `                ``if` `(``not` `visited[topo[j]]):` `                    ``print``(``str``(t) ``+` `'-'` `+` `                          ``str``(topo[j]), end``=``' '``)`   `                ``visited[topo[j]] ``=` `False`     `# Driver code` `if` `__name__ ``=``=` `'__main__'``:`   `    ``# Create a graph given in the` `    ``# above diagram` `    ``g ``=` `Graph(``6``)` `    ``g.addEdge(``5``, ``2``)` `    ``g.addEdge(``5``, ``0``)` `    ``g.addEdge(``4``, ``0``)` `    ``g.addEdge(``4``, ``1``)` `    ``g.addEdge(``2``, ``3``)` `    ``g.addEdge(``3``, ``1``)`   `    ``g.maximumEdgeAddition()`   `# This code is contributed by rutvik_56`

## C#

 `// C# program to find maximum edges after Adding` `// which graph still remains a DAG`   `using` `System;` `using` `System.Collections.Generic;`   `public` `class` `Graph {` `    ``private` `int` `V; ``// No. of vertices`   `    ``private` `List<``int``>[] adj; ``// adjacency list`   `    ``// array to store indegree of vertices` `    ``private` `int``[] indegree;`   `    ``// Constructor of graph` `    ``public` `Graph(``int` `v)` `    ``{` `        ``V = v;` `        ``indegree = ``new` `int``[V];` `        ``adj = ``new` `List<``int``>[ V ];` `        ``for` `(``int` `i = 0; i < V; i++) {` `            ``adj[i] = ``new` `List<``int``>();` `            ``indegree[i] = 0;` `        ``}` `    ``}`   `    ``// Utility function to Add edge` `    ``public` `void` `AddEdge(``int` `v, ``int` `w)` `    ``{` `        ``adj[v].Add(w); ``// Add w to v's list.`   `        ``// increasing inner degree of w by 1` `        ``indegree[w]++;` `    ``}`   `    ``// function to print maximum edges that can be Added` `    ``public` `List<``int``> TopologicalSort()` `    ``{`   `        ``List<``int``> topological = ``new` `List<``int``>();` `        ``Queue<``int``> q = ``new` `Queue<``int``>();`   `        ``// In starting push all node with indegree 0` `        ``for` `(``int` `i = 0; i < V; i++) {` `            ``if` `(indegree[i] == 0) {` `                ``q.Enqueue(i);` `            ``}` `        ``}`   `        ``while` `(q.Count > 0) {` `            ``int` `t = q.Dequeue();`   `            ``// push the node into topological list` `            ``topological.Add(t);`   `            ``// reducing inDegree of adjacent vertical` `            ``foreach``(``int` `j ``in` `adj[t])` `            ``{` `                ``indegree[j]--;`   `                ``// if inDegree becomes 0, just push` `                ``// into queue` `                ``if` `(indegree[j] == 0) {` `                    ``q.Enqueue(j);` `                ``}` `            ``}` `        ``}`   `        ``return` `topological;` `    ``}`   `    ``// The function prints all edges that can be` `    ``// Added without making any cycle` `    ``// It uses recursive topologicalSort()` `    ``public` `void` `MaximumEdgeAddition()` `    ``{` `        ``bool``[] visited = ``new` `bool``[V];` `        ``List<``int``> topo = TopologicalSort();`   `        ``// looping for all nodes` `        ``for` `(``int` `i = 0; i < topo.Count; i++) {` `            ``int` `t = topo[i];`   `            ``// In below loop we mark the adjacent node of t` `            ``foreach``(``int` `j ``in` `adj[t]) { visited[j] = ``true``; }`   `            ``for` `(``int` `j = i + 1; j < topo.Count; j++) {` `                ``// if not marked, then we can make an edge` `                ``// between t and j` `                ``if` `(!visited[topo[j]]) {` `                    ``Console.Write(t + ``"-"` `+ topo[j] + ``" "``);` `                ``}`   `                ``visited[topo[j]] = ``false``;` `            ``}` `        ``}` `        ``Console.WriteLine();` `    ``}`   `    ``// Driver code to test above methods` `    ``static` `void` `Main(``string``[] args)` `    ``{`   `        ``// Create a graph given in the above diagram` `        ``Graph g = ``new` `Graph(6);` `        ``g.AddEdge(5, 2);` `        ``g.AddEdge(5, 0);` `        ``g.AddEdge(4, 0);` `        ``g.AddEdge(4, 1);` `        ``g.AddEdge(2, 3);` `        ``g.AddEdge(3, 1);`   `        ``g.MaximumEdgeAddition();` `    ``}` `}`   `// This code is contributed by cavi4762.`

## Javascript

 `// javascript program to find maximum` `// edges after adding which graph` `// still remains a DAG` `class Graph{`   `    ``constructor(V){`   `        ``// No. of vertices` `        ``this``.V = V`   `        ``// Pointer to a list containing` `        ``// adjacency list` `        ``this``.adj = ``new` `Array(V);` `        ``for``(let i = 0; i < V; i++){` `            ``this``.adj[i] = ``new` `Array();` `        ``}` `        `  `        ``// Vector to store indegree of vertices` `        ``this``.indegree = ``new` `Array(V).fill(0);` `    ``}` `        `    `    ``// Utility function to add edge` `    ``addEdge(v, w){`   `        ``// Add w to v's list.` `        ``this``.adj[v].push(w)`   `        ``// Increasing inner degree of w by 1` `        ``this``.indegree[w] += 1` `    ``}`   `    ``// Main function to print maximum` `    ``// edges that can be added` `    ``topologicalSort(){`   `        ``let topological = ``new` `Array();` `        ``let q = ``new` `Array();`   `        ``// In starting append all node` `        ``// with indegree 0` `        ``for``(let i= 0; i < ``this``.V; i++){` `            ``if` `(``this``.indegree[i] == 0){` `                ``q.push(i);` `            ``}` `                `  `        ``}`   `        ``while` `(q.length != 0){` `            ``let t = q[0];` `            ``q.shift();`   `            ``// Append the node into topological` `            ``// vector` `            ``topological.push(t)`   `            ``// Reducing indegree of adjacent` `            ``// vertices` `            ``for``(let indx = 0; indx < ``this``.adj[t].length; indx++){` `                ``let j = ``this``.adj[t][indx];` `                `  `                ``this``.indegree[j] -= 1;` `                `  `                ``// If indegree becomes 0, just` `                ``// append into queue` `                ``if` `(``this``.indegree[j] == 0){` `                    ``q.push(j);` `                ``}` `            ``}` `        ``}`   `        ``return` `topological;` `    ``}`   `    ``// The function prints all edges that` `    ``// can be added without making any cycle` `    ``// It uses recursive topologicalSort()` `    ``maximumEdgeAddition(){`   `        ``let visited = ``new` `Array(``this``.V).fill(``false``);`   `        ``let topo = ``this``.topologicalSort();`   `        ``// Looping for all nodes` `        ``for``(let i = 0; i < topo.length; i++){` `            ``let t = topo[i];`   `            ``// In below loop we mark the` `            ``// adjacent node of t` `            ``for``(let indx = 0; indx < ``this``.adj[t].length; indx++){` `                ``let j = ``this``.adj[t][indx];` `                ``visited[j] = ``true``;` `            ``}`   `            ``// In below loop unmarked nodes` `            ``// are printed` `            `  `            ``for``(let j = i+1; j < topo.length; j++){`   `                ``// If not marked, then we can make` `                ``// an edge between t and j` `                ``if` `(!visited[topo[j]]){` `                    ``console.log(t.toString() + '-``' + topo[j].toString() + '` `');` `                ``}`   `                ``visited[topo[j]] = ``false``;` `            ``}` `        ``}` `    ``}` `}` `// Driver code`   `// Create a graph given in the` `// above diagram` `let g = ``new` `Graph(6);` `g.addEdge(5, 2);` `g.addEdge(5, 0);` `g.addEdge(4, 0);` `g.addEdge(4, 1);` `g.addEdge(2, 3);` `g.addEdge(3, 1);`   `g.maximumEdgeAddition();`   `// This code is contributed by gautam goel.`

Output

`4-5 4-2 4-3 5-3 5-1 2-0 2-1 0-3 0-1 `

Time complexity : O(V + E)

Space complexity : O(V + E)

## Optimized approach for finding only the number of edges that can be added

If we have to find only the maximum number of edges that can be added, it can be solved simply by understanding the following observation. If a DAG has n nodes, it has n nodes in it’s topological sort as well. The maximum number of edges a DAG can have can be determined by finding the maximum number of nodes that can be linked with each node. This implies the first node is connected to (n-1) nodes, the second node is connected to (n-2) nodes until the last node is not connected to any node. The reason for this decreasing pattern is because any edge from right node to the left node of the topological sort creates a cycle and it’ll no longer be a DAG.

This means a DAG of n nodes can have a maximum number of
(n-1) + (n-2) + (n-3) + . . . 3 + 2 + 1 = n*(n-1)/2 edges

If the DAG already has E edges, then the maximum number of additional edges that can be added is given by (n*(n-1)/2 – E) which will be our final answer.

Below is the code implementation of the optimized approach

## C++

 `#include ` `using` `namespace` `std;`   `int` `max_edges(``int` `V, ``int` `E) ` `{ ` `      ``return` `V * (V - 1) / 2 - E; ` `}`   `int` `main()` `{` `    ``int` `V, E;` `    ``// The number of vertices in the DAG` `    ``V = 6;` `    ``// The number of edges in the DAG` `    ``E = 6;` `      ``// Final output` `    ``cout << ``"Maximum number of edges that can be added to maintain DAG is "` `<< max_edges(V, E);` `    ``return` `0;` `}`

## Python3

 `def` `max_edges(V,E):` `    ``return` `V``*``(V``-``1``)``/``/``2` `-` `E`   `# The number of vertices in the DAG` `V ``=` `6` `# The number of edges in the DAG` `E ``=` `6` `# Final output` `print``(``"Maximum number of edges that can be added to maintain DAG is"``,max_edges(V,E))`

## Java

 `import` `java.io.*;`   `public` `class` `Main {`   `    ``static` `int` `max_edges(``int` `V, ``int` `E) {` `        ``return` `(V * (V - ``1``) / ``2``) - E;` `    ``}`   `    ``public` `static` `void` `main(String[] args) ``throws` `IOException {` `        ``BufferedReader reader = ``new` `BufferedReader(``new` `InputStreamReader(System.in));`   `        ``int` `V, E;` `        ``// The number of vertices in the DAG` `        ``V = ``6``;` `        ``// The number of edges in the DAG` `        ``E = ``6``;` `        ``// Final output` `        ``System.out.println(``"Maximum number of edges that can be added to maintain DAG is "` `+ max_edges(V, E));` `    ``}` `}`

## C#

 `using` `System;`   `class` `MainClass {` `    ``static` `int` `MaxEdges(``int` `V, ``int` `E) {` `        ``return` `(V * (V - 1) / 2) - E;` `    ``}`   `    ``public` `static` `void` `Main(``string``[] args) {` `        ``int` `V, E;` `        ``// The number of vertices in the DAG` `        ``V = 6;` `        ``// The number of edges in the DAG` `        ``E = 6;` `        ``// Final output` `        ``Console.WriteLine(``"Maximum number of edges that can be added to maintain DAG is "` `+ MaxEdges(V, E));` `    ``}` `}`

## Javascript

 `function` `maxEdges(V, E) {` `    ``return` `(V * (V - 1) / 2) - E;` `}`   `// The number of vertices in the DAG` `const V = 6;` `// The number of edges in the DAG` `const E = 6;` `// Final output` `console.log(`Maximum number of edges that can be added to maintain DAG is \${maxEdges(V, E)}`);`

Output

`Maximum number of edges that can be added to maintain DAG is 9`

Time Complexity: O(1)

Auxiliary Space: O(1)

NOTE: A DAG can have multiple topological sorting orders, but for each case, the maximum number of edges that can be added to maintain DAG remains same.

This article is contributed by Utkarsh Trivedi. 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.

My Personal Notes arrow_drop_up
Related Articles