📅  最后修改于: 2023-12-03 15:42:19.089000             🧑  作者: Mango
本题涉及有向图中的强连通分量(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