我试图在有向图中检测具有BFS算法的循环。我检测周期的主要想法是:因为BFS只访问每个节点(和边缘)一次,如果我再次遇到已经访问过的节点;它会导致一个循环。但是,我的代码有时会找到循环,有时不会。
我从维基百科修改的伪代码如下:
1 procedure BFS(G,v):
2 create a queue Q
3 enqueue v onto Q
4 mark v
5 while Q is not empty:
6 t <- Q.dequeue()
7 if t is what we are looking for:
8 return t
9 for all edges e in G.adjacentEdges(t) do
12 u <- G.adjacentVertex(t,e)
13 if u is not marked:
14 mark u
15 enqueue u onto Q
16 else:
17 print "Cycle detected!" //since we saw this node before
我错过了什么?
答案 0 :(得分:4)
您找到的算法可能会在找到周期之前找到目标节点(因此退出)。
对您来说哪个更重要:尽快找到目标或找到周期?如果您根本不关心目标,可以删除算法的那一部分。
答案 1 :(得分:0)
您的实施问题是它假定图表已连接。但实际情况是,您可能会处理具有两个连接部分的图形,因此如果您从v
开始,您将永远不会进入另一部分。要解决您的问题,您需要找到一种方法来识别可能未连接的子图。您可以在维基百科上找到一些建议http://en.wikipedia.org/wiki/Topological_sorting#Algorithms,在那里他们谈论
S ← Set of all nodes with no incoming edges
编辑:
实际上,您可以轻松进行更改,而不是将v
入队,将所有节点Dijkstra style排入队列。这样你应该总能找到你的周期。你也从哪里获得t
,因为它不是方法签名的一部分?
答案 2 :(得分:0)
即使没有循环,您提供的算法也可能会报告循环的存在。
在第12行,你我们在t附近。 BFS树中t的父也位于它的邻接列表中。
So, line 13 might return false even when no cycle exist because a parent of t is marked and is a part of t's adjacency list.
所以,我认为这个算法会报告一个周期,如果它存在,但它也可能报告一个周期,即使没有。
答案 3 :(得分:0)
您的算法将不会总是找到循环。因为,如果节点 v 在任何周期中都不存在,或者无法从节点 v 到达周期,则它将不起作用。我们可以做一些修改。 节点数等于 n 。 从每个节点运行bfs。 伪代码:
1 create a queue Q
2 create a array visited
3 create a array level
4 set answer = infinity
5 for each node 1 to **n**
6 mark the visited equals to **0**.
7 clear the **Q**
8 enqueue **v** onto Q
9 visited [ v ] = 1
10 while Q is not empty:
11 t <- Q.dequeue()
12 for all edges e in G.adjacentEdges(t) do
13 u <- G.adjacentVertex(t,e)
14 if u is not visited:
15 visited [ u ] = 1
16 level [ u ] = level [ t ] + 1;
17 enqueue u onto Q
18 else:
19 answer = min( answer , level [ t ] + level [ u ] + 1 )
算法完成后,您将获得整个图中最小的周期作为答案。