DFS-2个节点之间有多个循环

问题描述

尝试通过directed graphDFS中查找所有个周期。但是有一个问题。


问题

当2个节点之间存在多个循环时,有时只能检测到最长的一个,而跳过较短的一个

这是由于访问节点时,我将跳过它,因此跳过了较短的周期。 但是,如果我不跳过访问的节点,则DFS搜索将永远重复。


示例

图:

1 -> [2,4]
2 -> [3]
3 -> [4]
4 -> [1]

14之间有2个周期:

  • (A) 1-> 2-> 3-> 4-> 1
  • (B) 1-> 4-> 1

如果首先检测到A,则无法检测到周期B,因为4由于被访问而将被跳过,并且永远不会返回到1。


当前想法

  • 一个可能的解决方案是从每个节点开始,即使它已经被访问过。但是我想要一个更好的解决方案。
  • 计算并记住路径的哈希,仅当存在相同哈希时才跳过吗?那会需要一些记忆,对吗?而且,仍然存在2个具有相同哈希值的不同路径通向相同节点的可能性,这不能完全解决问题。

有什么主意吗?

解决方法

积分:https://www.hackerearth.com/practice/notes/finding-all-elementry-cycles-in-a-directed-graph/

integer list array A(n);logical array marked(n);integer stack current_stack ;integer stack marked_stack;/* A(n) is the array of list wich is adjacency list representation*/
 integer procedure intialize(); /*initialize the values*/
    begin;
    for i in n do 
         marked(i):=false
integer procedure print_cycles();
    begin
        for i in current_stack do
            print i ;       
logical procedure backtrack(k) do
    begin
        logical flag=false;
        current_stack->push(k);
        marked_stack->push(k);
        marked(n):=true;
        for i in A(k) do
            if i < s; /* To find only disticnt cycles in topological manner*/
               delete A(i);
            if i==s; /Cycle found */
                print_cycles()
            if marked(i):= false;
                backtrack(n); /*continue dfs*/
        if flag :=true;
            for i in marked_stack do /*unmark the elements that have been visited in any of the cycles starting from s*/
                marked(i):=false;
        current_stack->pop(k);
        backtrack:=flag
    end   backtrack(k)
begin 
    integer procedure backtrack_Util();
        begin
            for s in n do
               backtrack(s);
               while marked_stack(s)->empty do
                    for i in marked_stack do
                        marked(i):=false
     end backtrack_Util()

我们想找到不同的周期。因此,我们需要按一定顺序访问顶点。按照该顺序,我们需要找到从该顶点开始的循环,并且该循环中不应包含该顺序中起始顶点之前的任何顶点。如何获得该订单?上述评论之一中的topological manner一词与topological sort不明确,事实并非如此。我认为我们可以选择像顶点数字一样简单的排序,例如0,1,2,..,v。让我们说我们希望找到一个从2开始的循环。为了避免发现重复的循环,我们将不使用顶点0和1。如果有任何循环包含从2到1或2到0的边,查找从0或1开始的循环时已经考虑过。


让我介绍一个具体的参考资料,它将帮助您完成任务。它是Johnson's algorithm。显然,这是完成任务的最快方法。

在第3页上,它提到:

为避免电路重复,添加顶点v时将其阻塞 到以s开头的一些基本路径。只要它保持阻塞状态 从v到s的每个路径都与当前基本路径在a处相交 s以外的其他顶点。此外,顶点不会成为根 用于构造基本路径的顶点,除非它是最小顶点 在至少一个基本电路中。

您也可以观看this youtube video,以了解更多信息。

我认为这些信息是可以接受的。