[英]Detecting a cycle in an undirected graph using DFS
我有以下代碼,它是對DFS的修改,用於檢測無向圖是否具有循環。
graph = {
'A' : set(['B', 'C']),
'B' : set(['D', 'E', 'A']),
'C' : set(['A', 'F']),
'D' : set(['B']),
'E' : set(['B', 'F']),
'F' : set(['C','E'])
}
def find_cycle(graph, start):
colors = { node : "WHITE" for node in graph }
colors[start] = "GRAY"
stack = [start]
while stack:
for neighbor in graph[stack[-1]]:
if colors[neighbor] == "GRAY":
return True
elif colors[neighbor] == "WHITE":
colors[neighbor] = "GRAY"
stack.append(neighbor)
else:
colors[neighbor] = "BLACK"
stack.pop()
return False
無論我的圖是什么樣,它總是返回true,而我無法弄清楚我在做什么錯。 當我在紙上跟蹤該算法時,該算法有效,但實現方式無法轉換為有效代碼。
您的算法不適用於無向圖。 您很容易將周期檢測為A和B之間的第一個邊緣(B是A的鄰居,A是B的鄰居)。
您的代碼以鄰居的身份訪問了您剛來自的節點,因此您在同一邊上來回移動,卻發現您已經訪問了您實際來自的節點。 但是該算法錯誤地得出結論,這代表一個循環。
因此,僅檢查鄰居是否已被訪問還不夠。 如果相應的邊緣之前尚未移動過,則僅表示一個循環。
使算法起作用的一種方法是將邊緣存儲在堆棧中,而不僅僅是節點。 然后,您可以輕松地檢查鄰居是否在邊緣的另一端,然后忽略它:
def find_cycle(graph, start):
colors = { node : "WHITE" for node in graph }
colors[start] = "GRAY"
stack = [(None, start)] # store edge, but at this point we have not visited one
while stack:
(prev, node) = stack.pop() # get stored edge
for neighbor in graph[node]:
if neighbor == prev:
pass # don't travel back along the same edge we came from
elif colors[neighbor] == "GRAY":
return True
else: # can't be anything else than WHITE...
colors[neighbor] = "GRAY"
stack.append((node, neighbor)) # push edge on stack
return False
請注意,您在問題中顯示的圖形具有一個循環:
A---C
/ \
B---E---F
例如,如果刪除C和F之間的連接,則上面的代碼將返回False
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.