📌  相关文章
📜  可以添加到 DAG 以使其保持 DAG 的最大边数

📅  最后修改于: 2022-05-13 01:57:54.403000             🧑  作者: Mango

可以添加到 DAG 以使其保持 DAG 的最大边数

给了我们一个 DAG,我们需要找到可以添加到该 DAG 的最大边数,之后新图仍然是 DAG,这意味着重组后的图应该有最大的边数,即使添加单个边也会创建一个图中的循环。

可以添加到 DAG 以使其保持 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

如上例所示,我们在一个方向上添加了所有边,只是为了避免循环。这是解决这个问题的诀窍。我们按拓扑顺序对所有节点进行排序,并创建从节点到右侧的所有节点的边(如果还没有的话)。
我们怎么能这么说,不可能再添加任何边缘?原因是我们已经从左到右添加了所有可能的边,如果我们想添加更多的边,我们需要从右到左,但是从右到左添加边我们肯定会创建一个循环,因为它的对应部分从左到右边已经被添加到图中,创建循环不是我们需要的。
所以解决方案如下,我们按照拓扑顺序考虑节点,如果从左到右没有任何边,我们将创建它。

下面是解决方案,我们打印了所有可以添加到给定 DAG 的边,而无需进行任何循环。

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* adj;
  
    // Vector to store indegree of vertices
    vector indegree;
  
    // function returns a topological sort
    vector 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[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 Graph::topologicalSort()
{
    vector topological;
    queue 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::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 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::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> 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 maximumEdgeAddtion()
  {
    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.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


输出:

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