Согласно лемме 22.11 из Кормен и др., Введение в алгоритмы (CLRS):
Ориентированный граф G является ацикличным тогда и только тогда, когда поиск G в глубину не дает обратных ребер.
Об этом упоминалось в нескольких ответах; здесь я также приведу пример кода, основанный на главе 22 CLRS. Пример графика проиллюстрирован ниже.
![введите описание изображения здесь](https://i.stack.imgur.com/RrsDe.png)
Псевдокод CLRS для поиска в глубину гласит:
![введите описание изображения здесь](https://i.stack.imgur.com/MIlwU.png)
В примере, показанном на рис. 22.4 CLRS, граф состоит из двух деревьев DFS: одно состоит из узлов u, v, x и y, а другой из узлов w и z. Каждое дерево содержит один задний край: один от x до v, а другой от z до z (само- петля).
Ключевая реализация состоит в том, что задний край встречается, когда в функции DFS-VISIT
при итерации по соседям v
из u
встречается узел с цветом GRAY
.
Следующий код Python представляет собой адаптацию псевдокода CLRS с добавленным предложением if
, которое обнаруживает циклы:
import collections
class Graph(object):
def __init__(self, edges):
self.edges = edges
self.adj = Graph._build_adjacency_list(edges)
@staticmethod
def _build_adjacency_list(edges):
adj = collections.defaultdict(list)
for edge in edges:
adj[edge[0]].append(edge[1])
return adj
def dfs(G):
discovered = set()
finished = set()
for u in G.adj:
if u not in discovered and u not in finished:
discovered, finished = dfs_visit(G, u, discovered, finished)
def dfs_visit(G, u, discovered, finished):
discovered.add(u)
for v in G.adj[u]:
# Detect cycles
if v in discovered:
print(f"Cycle detected: found a back edge from {u} to {v}.")
# Recurse into DFS tree
if v not in finished:
dfs_visit(G, v, discovered, finished)
discovered.remove(u)
finished.add(u)
return discovered, finished
if __name__ == "__main__":
G = Graph([
('u', 'v'),
('u', 'x'),
('v', 'y'),
('w', 'y'),
('w', 'z'),
('x', 'v'),
('y', 'x'),
('z', 'z')])
dfs(G)
Обратите внимание, что в этом примере time
в псевдокоде CLRS не захватывается, потому что нас интересует только обнаружение циклов. Существует также некоторый шаблонный код для построения представления списка смежности графа из списка ребер.
Когда этот сценарий выполняется, он выводит следующий результат:
Cycle detected: found a back edge from x to v.
Cycle detected: found a back edge from z to z.
Это в точности задние края в примере на рис. 22.4 CLRS.
person
Kurt Peek
schedule
01.01.2019