问题是:给定一个有向图,找到图中最长的简单循环。我已经搜索了问题,并找到了此链接Finding the longest cycle in a directed graph using DFS。答案解释了这是一个NP难题。
但是我对以下算法感到困惑,它似乎在O(| V | + | E |)时间中运行,因为我们只对每个边进行了一次访问。
保持以下变量:
(1)global max
:图中最长循环的长度。
(2)Map<GraphNode, Integer> cache
:存储从关键节点开始的最长周期的长度。
(3)Map<GraphNode, Integer> pathVisited
:存储路径上已访问的节点和相应的步骤号。例如,A-> B-> C-> A,如果从A开始,地图将看起来像{A-> 1,B-> 2,C-> 3},并且再次输入A时,步骤变为4,因此周期长度为4-1 = 3
(4)Set<GraphNode> visited
:包含已被充分研究的graphNode。
dfs(GraphNode cur, int curStep, Set<GraphNode> visited, Map<GraphNode, Integer> cache, Map<GraphNode, Integer> pathVisited):
if visited.containsKey(cur), then
return // if the node have been explored, no need to explore again
// if see a cycle, update the results(cache)
if pathVisited.containsKey(cur), then
newCycleLen = curStep - pathVisited.get(cur)
cache.put(cur, max {newCycleLen, cache.get(cur)})
return
// no cycle yet, continue the search
pathVisited.put(cur, curStep)
for each neighbor of cur:
dfs(neighbor, curStep + 1, cache, pathVisited)
endfor
visited.add(cur); // current node have been explored, in the future no need to visit it again.
path.remove(cur)
我认为上述算法可以在O(| V | + | E |)时间内解决问题,因为在完全探查一个节点之后,我们将不再在该节点上开始dfs。
任何人都可以给我一些有关上述算法为何错误的提示吗?
答案 0 :(得分:1)
请考虑以下图形:
D -- A
/ | |
E | |
\ | |
C -- B
现在,假设您在节点A上启动DFS,并按顺序B,C,D,E依次访问节点。除非我误解了您的代码在做什么,否则我不相信这访问顺序将使您能够找到最长的循环A,B,C,E,D,A,因为一旦访问了D,就将其分配给错误的深度,并切断返回A的路径。
答案 1 :(得分:0)
我认为问题是什么是“基本周期”。如果周期一次都访问了所有点,则DFS很好。但这是问题:
A---B
|\ /|
| E |
|/ \|
C---D
假设方向:
A-> B
B-> D,E
C-> D
D-> E,A
E-> C
DFS将发现最长周期为5,A-> B-> E-> C-> D-> A,但最长周期应为A-> B-> E-> C-> D-> E->一种。也许您应该尝试使用新视图