[英]Optimizing the algorithm of detecting cycle in a graph using python
我已經使用dfs實現了此代碼,以檢測圖形中是否有一個循環,如果有,還打印該循環的頂點。 如果有多個循環,則只需打印找到的第一個循環即可。 但是OJ以某種方式告訴我,對於某些測試用例而言,效率還不夠高。 關於如何提高這段代碼效率的任何想法嗎?
我一直在認真思考如何改善這一點,但沒有任何進展。 我想也許我應該嘗試使用除dfs之外的其他算法?
# using python3
from collections import defaultdict
class Graph():
def __init__(self, V):
self.V = V
self.graph = defaultdict(list)
def add_edge(self, u, v):
self.graph[u].append(v)
def dfs_walk(self, u):
# List to contain the elements of a circle
list_circle = list()
# Mark visited vertexes
visited = list()
stack = [u]
while stack:
v = stack.pop()
visited.append(v)
# If already in list_circle, means there is a circle.
if v in list_circle:
return True, list_circle[list_circle.index(v):], visited
# If v is not in list_circle and it has neighbor, collect it in the list,
# go to next vertex. If it hasn't neighbor, check the left vertex
else:
# the next vertex is the first neighbor of this vertex
if len(self.graph[v]) > 0:
stack.extend(self.graph[v])
list_circle.append(v)
# Didn't find a circle in this round.
return False, list_circle, visited
def is_cyclic(self):
control = [-1] * self.V
for i in range(self.V):
if control[i] == -1:
flag, list_circle, visited = self.dfs_walk(i)
for x in visited:
control[x] = 0
if flag:
return True, list_circle
# Didn't find any circle in all rounds.
return False, list_circle
if __name__ == "__main__":
line = input().split()
V, E = int(line[0]), int(line[1])
# Initialize the graph
g = Graph(V)
for r in range(E):
row = input().split()
start, end = int(row[0])-1, int(row[1])-1
g.add_edge(start, end)
flag, list_circle = g.is_cyclic()
if flag:
print("YES")
print(" ".join(str(i+1) for i in list_circle))
else:
print("NO")
第一行是頂點數和邊數。 在第一行之后,每條線代表一條邊(有向)。
輸入:
3 3
1 2
2 3
3 1
輸出:
是
1 2 3
我會說這段代碼效率不是很高。 為什么您有list_circle
並以不同的方式visited
? 同樣將它們存儲為list
意味着v in list_circle
檢查中的v in list_circle
需要O(n)
所以整個算法可能是O(n^2)
。 我認為對您來說,一個不好的例子是“ P”,但循環很小,行很長,您從該行的底部開始,因此您必須遍歷整個行,直到最終找到循環為止。
我懷疑如果將它們合並到單個dict()
以將DFS結果存儲為
visited[child] = parent
很難為此創建一個不好的案例,並且您仍然可以通過從第一個雙重訪問的點沿兩種方式返回,輕松地根據該信息重新構造一個循環。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.