用python优化图的圈检测算法
我已经使用dfs实现了这段代码,以检测图形中是否存在循环,如果存在,还可以打印此循环的顶点。如果有多个周期,只需打印找到的第一个周期。但不知怎的,OJ告诉我,对于一些测试用例来说,它的效率不够。关于如何提高这段代码的效率有什么想法吗 我一直在努力思考如何改进这一点,但没有任何进展。我想也许我应该尝试使用dfs以外的其他算法用python优化图的圈检测算法,python,algorithm,graph,Python,Algorithm,Graph,我已经使用dfs实现了这段代码,以检测图形中是否存在循环,如果存在,还可以打印此循环的顶点。如果有多个周期,只需打印找到的第一个周期。但不知怎的,OJ告诉我,对于一些测试用例来说,它的效率不够。关于如何提高这段代码的效率有什么想法吗 我一直在努力思考如何改进这一点,但没有任何进展。我想也许我应该尝试使用dfs以外的其他算法 # using python3 from collections import defaultdict class Graph(): def __init__(
# 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
意味着v在list\u循环中
检查需要O(n)
,因此整个算法可能是O(n^2)
。我认为对你来说,一个糟糕的例子是类似于“P”的东西,但是有一个很小的循环,有一条很长的线,你从那条线的底部开始,所以你必须走整条线,直到你最终找到循环
我怀疑如果您将它们合并到一个dict()
中以将DFS结果存储为
visited[child] = parent
为它创建一个坏的案例将更加困难,您仍然可以通过从第一个双访问点沿两条路径返回来轻松地从该信息重新构建一个循环。如果代码是正确的,但只需要性能改进,那么应该在代码审查中,而不是在这里。请注意,尽管它们需要工作的完整代码,但您在这里有点重新发明轮子。您对使用图形库的解决方案感兴趣吗?@wim这是一项OJ任务,不允许使用库