Theo Bổ đề 22.11 của Cormen và cộng sự, Giới thiệu về Thuật toán (CLRS):
Đồ thị có hướng G là theo chu kỳ khi và chỉ khi tìm kiếm theo chiều sâu của G không có cạnh sau.
Điều này đã được đề cập trong một số câu trả lời; ở đây tôi cũng sẽ cung cấp một ví dụ mã dựa trên chương 22 của CLRS. Biểu đồ ví dụ được minh họa dưới đây.
Mã giả của CLRS cho tìm kiếm theo chiều sâu đọc:
Trong ví dụ trong CLRS Hình 22.4, biểu đồ bao gồm hai cây DFS: một bao gồm các nút u , v , x và y và một nút khác của các nút w và z . Mỗi cây chứa một cạnh sau: một từ x đến v và một cây khác từ z đến z (một vòng lặp tự).
Nhận thức chính là một cạnh sau gặp phải khi, trong DFS-VISIT
hàm, trong khi lặp qua các hàng xóm v
của u
, một nút được bắt gặp với GRAY
màu.
Mã Python sau đây là sự điều chỉnh mã giả của CLRS với một if
mệnh đề được thêm vào để phát hiện các chu kỳ:
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)
Lưu ý rằng trong ví dụ này, time
mã giả trong CLRS không bị bắt vì chúng tôi chỉ quan tâm đến việc phát hiện các chu kỳ. Ngoài ra còn có một số mã soạn sẵn để xây dựng biểu diễn danh sách kề của biểu đồ từ danh sách các cạnh.
Khi đoạn script này được thực thi, nó sẽ in ra kết quả sau:
Cycle detected: found a back edge from x to v.
Cycle detected: found a back edge from z to z.
Đây chính xác là các cạnh sau trong ví dụ trong CLRS Hình 22.4.