Skip to content
Related Articles

Related Articles

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

View Discussion
Improve Article
Save Article
  • Difficulty Level : Medium
  • Last Updated : 05 Jul, 2022

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.

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

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 <bits/stdc++.h>
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 maximumEdgeAddtion();
};
 
//  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::maximumEdgeAddtion()
{
    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.maximumEdgeAddtion();
    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<ArrayList<Integer>> 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<Integer>());
      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<Integer> topologicalSort() 
  {
 
    List<Integer> topological = new ArrayList<>(V);
    Queue<Integer> 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 maximumEdgeAddtion()
  {
    boolean[] visited = new boolean[V];
    List<Integer> 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<Integer> 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.maximumEdgeAddtion();
    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 maximumEdgeAddtion(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.maximumEdgeAddtion()
 
# 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 MaximumEdgeAddtion()
    {
        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.MaximumEdgeAddtion();
    }
}
 
// This code is contributed by cavi4762.


Output

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

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
Recommended Articles
Page :

Start Your Coding Journey Now!