在定向图中查找所有周期,包括后边缘
给定下面的图,找到从顶点1
返回到1
的所有可能路径,包括后边。
结果:
[1,2,3,2,1]
[1,2,1]
[1,2,3,1]
我尝试使用 DFS 只能获得一个周期[1,2,3,2,1]
。我不知道如何跟踪后边缘。
代码:
private static void dfsNow(Node vertex, HashMap<String, List<Node>> adjList,
HashSet<String> visited, HashSet<String> candidates,
ArrayList<String> res) {
candidates.add(vertex.v);
res.add(vertex.v);
for(Node adj : adjList.get(vertex.v)) {
if(candidates.contains(adj.v)) {
res.add(adj.v);
System.out.println(vertex.v+":"+adj.v);
} else {
//adj.setParent(vertex); // build the trace back
dfsNow( adj, adjList,visited,candidates,res);
}
}
candidates.remove(vertex.v);
visited.add(vertex.v);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
你已经很接近答案了。
为了检测图形中的循环,您需要使用深度优先搜索算法。这是正确的。
但您的解决方案中有一些地方需要改进:
List
。>
List
进行contains()
检查的成本非常高(O(n)在最坏的情况下),并且列表无法关联元素。Map
是一个更好的选择,因为 Map 允许在恒定时间内检索值并将多个键与相同的值相关联(即一组顶点与单个顶点连接时的模型情况)。请注意,循环
[1,2,3,2,1]
无效,因为有多个顶点被访问了两次。它是两个周期1-2
和2-3
的组合。如果您需要发现图表中的所有循环,则一次只能检测到一个循环,否则尝试恢复循环路径可能会失败,因为引用相互指向。只是因为您的解决方案只能跟踪单个路径,所以您不会在第二个循环2->3->2
中遇到麻烦。即循环中的所有顶点(除了一个)必须是唯一的,这将允许维护多个路径。在下面的实现中,我特意提供了一种能够检测包含特定顶点的循环的方法,以及一种获取仅包含唯一顶点的所有循环的方法。这样您就可以通过更改它们来进行尝试,并确保map永远不包含循环的最后一段。即只有条目
2->3
会被添加到映射中,但条目3->2
不会,否则您可以创建无限循环。下图的实现仅使用顶点。深度优先搜索算法以迭代方式实现(尽管递归实现更容易,但递归在 Java 中存在局限性,尤其是在处理大型数据集时,并且迭代方法的性能更高)。
演示中使用的更复杂的图表示例以及问题中提供的图表。
main()
- 演示输出
You were close to the answer.
In order to detect a cycle in a graph, you need to use the Depth first search algorithm. That's correct.
But there are a couple of things in your solution that has to improved:
List<List<Vertex>>
.contains()
checks done on aList
are very costful (O(n) in the worse case), and isn't list capable to associate elements.Map
is a better choice because map allow to retrieve values in a constant time and associate multiple keys with the same value (i.e. model cases when a group of vertices points is being connected with a single vertex).Note that cycle
[1,2,3,2,1]
isn't valid because there's more than one vertex that was visited twice. It's a combination of two cycles1-2
and2-3
. If you need to spot all the cycles in a graph they must be detected only one at a time, otherwise attempt to restore the path of a cycle might fail because of references pointing one at each other. Only because in your solution is capable to track only a single path, you didn't run in to trouble with the second cycle2->3->2
. I.e. all vertexes (except one) in a cycle must be unique, that will allow to maintain multiple paths.In the implementation below, I deliberately provided a method that is able to detect cycles that contain a particular vertex, as well a method that fetches all the cycles comprised of only unique vertices. So that you can play around by changing them and make sure that map should never contain the last segment of cycle. I.e. only entry
2->3
will be added by into map, but entry3->2
will not, otherwise you can create an infinite loop.Implementation of the graph below utilizes only vertexes. Depth first search algorithm is implemented iteratively (although recursive implementation is easier, recursion has limitation in Java especially when dealing with a large dataset and iterative approach is more performant).
Example of a bit more elaborate graph used in demo together with the graph provided in the question.
main()
- demoOutput