Return 使用 Kahn 算法的图形中的所有拓扑排序顺序?

Return all topological sort orderings in a graph using Kahn's algorithm?

我正在尝试解决一种情况,我已经实现了卡恩的算法来查找和 return 图中的一种拓扑排序。但是,我想尝试实现这个以便 return 所有拓扑顺序。例如,如果一个图有 4 个具有以下边的节点:

(1 2)
(1 3)
(2 3)
(2 4)

它将return以下两种可能的拓扑顺序:

[1 2 3 4] 
[1 2 4 3]

无论如何我可以用下面的代码来做这个:

from collections import defaultdict 

#Class to represent a graph 
class Graph: 
    def __init__(self,vertices): 
        self.graph = defaultdict(list) #dictionary containing adjacency List 
        self.V = vertices #No. of vertices 

    # function to add an edge to graph 
    def addEdge(self,u,v): 
        self.graph[u].append(v) 


    # The function to do Topological Sort.  
    def topologicalSort(self): 

        # Create a vector to store indegrees of all 
        # vertices. Initialize all indegrees as 0. 
        in_degree = [0]*(self.V) 

        # Traverse adjacency lists to fill indegrees of 
           # vertices.  This step takes O(V+E) time 
        for i in self.graph: 
            for j in self.graph[i]: 
                in_degree[j] += 1

        # Create an queue and enqueue all vertices with 
        # indegree 0 
        queue = [] 
        for i in range(self.V): 
            if in_degree[i] == 0: 
                queue.append(i) 

        #Initialize count of visited vertices 
        cnt = 0

        # Create a vector to store result (A topological 
        # ordering of the vertices) 
        top_order = [] 

        # One by one dequeue vertices from queue and enqueue 
        # adjacents if indegree of adjacent becomes 0 
        while queue: 

            # Extract front of queue (or perform dequeue) 
            # and add it to topological order 
            u = queue.pop(0) 
            top_order.append(u) 

            # Iterate through all neighbouring nodes 
            # of dequeued node u and decrease their in-degree 
            # by 1 
            for i in self.graph[u]: 
                in_degree[i] -= 1
                # If in-degree becomes zero, add it to queue 
                if in_degree[i] == 0: 
                    queue.append(i) 

            cnt += 1

        # Check if there was a cycle 
        if cnt != self.V: 
            print "There exists a cycle in the graph"
        else : 
            #Print topological order 
            print top_order 

 #Test scenario
 g = Graph(4);
 g.addEdge(1, 2);
 g.addEdge(1, 2);
 g.addEdge(2, 3);
 g.addEdge(2, 4);

 g.topologicalSort()

您的问题陈述与 NetworkX all topo sorts 函数匹配。

如果您只想要结果,我建议按原样调用它们的函数。

如果你想破解一个实现,他们的源代码可能会告诉你自己的。在那种情况下,您可能会选择从 Kahn 的算法切换到他们引用的 Knuth 的算法。

请注意,图节点索引以 0:

开头
g.addEdge(1, 2);  # replace with 0, 1 and so on

通过这个修改,这个算法returns只有一个拓扑排序,而图可以有更多的排序,因为我们总是select只有队列中的第一个项目。要获得所有排序,您可以使用此修改后的代码:

from collections import defaultdict

#Class to represent a graph 
class Graph:
    def __init__(self, vertices):
        self.graph = defaultdict(list) #dictionary containing adjacency List 
        self.V = vertices #No. of vertices 

    # function to add an edge to graph 
    def addEdge(self, u, v):
        self.graph[u].append(v)


    # The function to do Topological Sort.  
    def topologicalSort(self): 

        # Create a vector to store indegrees of all 
        # vertices. Initialize all indegrees as 0. 
        in_degree = [0] * self.V

        # Traverse adjacency lists to fill indegrees of 
        # vertices.  This step takes O(V+E) time 
        for i in self.graph:
            for j in self.graph[i]:
                in_degree[j] += 1

        # Create an queue and enqueue all vertices with 
        # indegree 0 
        queue = []
        for i in range(self.V):
            if in_degree[i] == 0:
                queue.append(i)

        self.process_queue(queue[:], in_degree[:], [], 0)

    def process_queue(self, queue, in_degree, top_order, cnt):
        if queue:

            # We have multiple possible next nodes, generate all possbile variations
            for u in queue:

                # create temp copies for passing to process_queue
                curr_top_order = top_order + [u]
                curr_in_degree = in_degree[:]
                curr_queue = queue[:]
                curr_queue.remove(u)

                # Iterate through all neighbouring nodes 
                # of dequeued node u and decrease their in-degree 
                # by 1 
                for i in self.graph[u]:
                    curr_in_degree[i] -= 1
                    # If in-degree becomes zero, add it to queue 
                    if curr_in_degree[i] == 0:
                        curr_queue.append(i)

                self.process_queue(curr_queue, curr_in_degree, curr_top_order, cnt + 1)  # continue recursive

        elif cnt != self.V:
            print("There exists a cycle in the graph")
        else:
            #Print topological order 
            print(top_order)


g = Graph(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 2);
g.addEdge(1, 3);

g.topologicalSort()

输出:

[0, 1, 2, 3]

[0, 1, 3, 2]