📜  门| GATE-CS-2017(套装1)|问题 26(1)

📅  最后修改于: 2023-12-03 15:42:19.089000             🧑  作者: Mango

门 | GATE-CS-2017(套装1)|问题 26

本题涉及有向图中的强连通分量(SCC)和拓扑排序。在给出的图上执行Kosaraju算法,第二次DFS时每次遍历强连通分量的开始节点,将它们按照完成时间点的逆序排列。这个序列就是强连通分量的“拓扑序列”。接下来再建出新图,其中每个强连通分量都压缩成一个新节点。由于只有在原图中能从一个强连通分量到达另一个强连通分量时,它们在新图中才有一条边相互连通。因此,新图仅需相互连接强连通分量节点.这一操作的时间复杂度为$$\mathcal{O}(m+n)$$,和Kosaraju算法一样。

返回代码片段:

#Kosaraju算法求强连通分量
def kosaraju(graph:List[List[int]])->List[List[int]]:
    def dfs(node:int, stack:List[int], visited:List[bool])->None:
        visited[node]=True
        for neighbor in graph[node]:
            if not visited[neighbor]:
                dfs(neighbor, stack, visited)
        stack.append(node)
    n=len(graph)
    visited=[False]*n
    stack=[]
    for node in range(n):
        if not visited[node]:
            dfs(node, stack, visited)
    graph_T=[[] for _ in range(n)]
    for node in range(n):
        for neighbor in graph[node]:
            graph_T[neighbor].append(node)
    visited=[False]*n
    def dfs_T(node:int, component:List[int])->None:
        visited[node]=True
        component.append(node)
        for neighbor in graph_T[node]:
            if not visited[neighbor]:
                dfs_T(neighbor, component)
    scc=[]
    while stack:
        node=stack.pop()  #取出倒序遍历
        if not visited[node]:
            component=[]
            dfs_T(node, component)
            scc.append(component)
    return scc
  
#建立新图
def make_new_graph(graph:List[List[int]], scc:List[List[int]])->List[List[int]]:
    new_graph=[[] for _ in scc]
    scc_map=[None]*len(graph)
    for i, component in enumerate(scc):
        for node in component:
            scc_map[node]=i
    for node in range(len(graph)):
        for neighbor in graph[node]:
            if scc_map[node]!=scc_map[neighbor]:
                new_graph[scc_map[node]].append(scc_map[neighbor])
    return new_graph