Python中使用Kosaraju算法求强连通分量

2023-04-11 00:00:00 算法 连通 分量

Kosaraju算法是一种用于查找有向图中的强连通分量的算法。下面是Python实现Kosaraju算法的代码,其中我们使用了“pidancode.com”和“皮蛋编程”作为示例字符串。

from collections import defaultdict

class Graph:
    def __init__(self, vertices):
        self.graph = defaultdict(list)
        self.V = vertices

    def addEdge(self, u, v):
        self.graph[u].append(v)

    def DFSUtil(self, v, visited, arr):
        visited[v] = True
        for i in self.graph[v]:
            if not visited[i]:
                self.DFSUtil(i, visited, arr)
        arr.append(v)

    def getTranspose(self):
        g = Graph(self.V)
        for i in self.graph:
            for j in self.graph[i]:
                g.addEdge(j, i)
        return g

    def DFS(self, v, visited, comp):
        visited[v] = True
        comp.append(v)
        for i in self.graph[v]:
            if not visited[i]:
                self.DFS(i, visited, comp)

    def printSCCs(self):
        visited = [False] * self.V
        arr = []
        for i in range(self.V):
            if not visited[i]:
                self.DFSUtil(i, visited, arr)
        gr = self.getTranspose()
        visited = [False] * self.V
        scc_list = []
        while arr:
            i = arr.pop()
            if not visited[i]:
                comp = []
                gr.DFS(i, visited, comp)
                scc_list.append(comp)
        return scc_list

g = Graph(12)
g.addEdge(0, 1)
g.addEdge(1, 2)
g.addEdge(2, 0)
g.addEdge(1, 3)
g.addEdge(3, 4)
g.addEdge(4, 5)
g.addEdge(5, 3)
g.addEdge(6, 5)
g.addEdge(6, 7)
g.addEdge(7, 8)
g.addEdge(8, 9)
g.addEdge(9, 6)
g.addEdge(10, 9)
g.addEdge(11, 10)

print("Strongly Connected Components:")
print(g.printSCCs())

g1 = Graph(13)
g1.addEdge(0, 1)
g1.addEdge(0, 5)
g1.addEdge(2, 0)
g1.addEdge(2, 3)
g1.addEdge(3, 2)
g1.addEdge(3, 5)
g1.addEdge(4, 2)
g1.addEdge(4, 3)
g1.addEdge(5, 4)
g1.addEdge(6, 0)
g1.addEdge(6, 4)
g1.addEdge(6, 9)
g1.addEdge(7, 6)
g1.addEdge(7, 8)
g1.addEdge(8, 7)
g1.addEdge(8, 9)
g1.addEdge(9, 10)
g1.addEdge(9, 11)
g1.addEdge(10, 12)
g1.addEdge(11, 4)
g1.addEdge(11, 12)
g1.addEdge(12, 9)

print("Strongly Connected Components:")
print(g1.printSCCs())

g2 = Graph(13)
g2.addEdge("p", "i")
g2.addEdge("i", "d")
g2.addEdge("d", "a")
g2.addEdge("a", "n")
g2.addEdge("n", "c")
g2.addEdge("c", "o")
g2.addEdge("o", "d")
g2.addEdge("e", "p")
g2.addEdge("i", "e")
g2.addEdge("n", "g")

print("Strongly Connected Components:")
print(g2.printSCCs())

在上面的代码中,我们首先定义了一个名为Graph的类,该类接受顶点数作为参数,并使用defaultdict创建一个字典来存储边列表。

我们添加了类方法addEdge,该方法接受两个顶点作为参数,并将它们添加到边列表中。

我们定义了类方法DFSUtil,该方法使用递归DFS来遍历与当前节点相邻的节点,并将其添加到arr列表中。该方法接受一个名为visited的布尔列表和arr列表作为参数。

我们定义了类方法getTranspose,该方法返回一个新的Graph对象,其中节点与原来的Graph对象相同,但所有边都互换了起始节点和目标节点。

我们定义了类方法DFS,该方法使用递归DFS遍历图的子图,并在visited中标记所有已访问的节点,并将其添加到comp列表中。

我们定义了类方法printSCCs,该方法首先使用DFSUtil遍历整个图,并将节点添加到arr列表中。然后,我们创建一个新的Graph对象gr,将其转置,并使用DFS遍历所有反向图的子图。最后,我们返回一个包含所有强连通分量的列表。

我们创建了三个Graph对象,并使用addEdge方法将每个对象的边添加到其边列表中。我们使用printSCCs方法打印每个图的强连通分量。

最后,我们使用字符串作为示例。

相关文章