我想要实现的功能找到所有可能的路径,以所有可能的折点的一个来源的顶点V在针对循环图G

性能现在不要紧,我只是想了解的算法。我已经阅读的定义深先搜索算法,但是我没有完全理解要做什么。

我没有任何已完成的代码,以提供这里,因为我不知道该如何:

  • 结果存储(与一个->B>C->我们还应该商店一个->B和A->B>C);
  • 代表的图表(图?清单元组?);
  • 多少递归来使用(工作与每个相邻的顶点?).

我怎么能找到所有可能的路径,形成一个特定来源的顶点,在针对循环中的曲线图二郎?

UPD:基于答案,所以到目前为止,我已经重新定义的曲线定义:这是一个非环曲线图。我知道,如果我递归功能命周期是无限的循环。为了避免这种情况,我只能检查,如果当前的顶点是在该列表中所得到的路-如果是的话,我停止遍和返回的路径。


UPD2: 谢谢你的发人深省的意见!是的,我需要找到简单的所有道路,没有从循环的一个来源的顶点到所有其他人。

在一个曲线图这样的:

Non-acyclic graph

与源顶点的一种算法应该找到下面的路径:

  • A,B
  • A、B、C
  • A、B、C、D
  • 一、D
  • A、D、C
  • A,D,C,B

以下代码的工作,但它是无法使用的与图形,有更多的20顶点(我想这是错误的东西用递归-需要太多的记忆,永远不会结束):

dfs(Graph,Source) ->
    ?DBG("Started to traverse graph~n", []),
            Neighbours = digraph:out_neighbours(Graph,Source),
    ?DBG("Entering recursion for source vertex ~w~n", [Source]),
            dfs(Neighbours,[Source],[],Graph,Source),
ok.


dfs([],Paths,Result,_Graph,Source) ->
    ?DBG("There are no more neighbours left for vertex ~w~n", [Source]),
    Result;

dfs([Neighbour|Other_neighbours],Paths,Result,Graph,Source) ->
    ?DBG("///The neighbour to check is ~w, other neighbours are: ~w~n",[Neighbour,Other_neighbours]),
    ?DBG("***Current result: ~w~n",[Result]),
    New_result = relax_neighbours(Neighbour,Paths,Result,Graph,Source),

        dfs(Other_neighbours,Paths,New_result,Graph,Source).


relax_neighbours(Neighbour,Paths,Result,Graph,Source) ->
     case lists:member(Neighbour,Paths) of 
        false ->
            ?DBG("Found an unvisited neighbour ~w, path is: ~w~n",[Neighbour,Paths]),
            Neighbours = digraph:out_neighbours(Graph,Neighbour),
            ?DBG("The neighbours of the unvisited vertex ~w are ~w, path is:
                ~w~n",[Neighbour,Neighbours,[Neighbour|Paths]]),
                dfs(Neighbours,[Neighbour|Paths],Result,Graph,Source);
            true ->
                [Paths|Result]

        end.

UPD3:

问题是,经常深入的先搜索算法将进一路径的第一个:(A,B,C,D)或(A,D,C,B)和将永远不会去的第二个道路。

在这两种情况下,它将能的唯一道路,例如,当正常的外勤部将回溯自(A,B,C,D)它可以追溯到一个和检查,如果D(第二邻居一)被访问。和由于正常的外勤部维持一个全球国家为每一个顶点,D会'与'的状态。

因此,我们必须引进递归依赖状态--如果我们原路返回自(A,B,C,D)达,我们应该(A,B,C,D)列表中的结果,我们应该有D标记为未访问,为在开始的算法。

我已经试过优化解决方案的尾巴-recursive之一,但仍然运转的时间的算法是不可行需要大约4秒钟穿越一个小小的图16顶点,有3个边缘每顶点:

dfs(Graph,Source) ->
    ?DBG("Started to traverse graph~n", []),
            Neighbours = digraph:out_neighbours(Graph,Source),
    ?DBG("Entering recursion for source vertex ~w~n", [Source]),
    Result = ets:new(resulting_paths, [bag]),
Root = Source,
            dfs(Neighbours,[Source],Result,Graph,Source,[],Root).


dfs([],Paths,Result,_Graph,Source,_,_) ->
    ?DBG("There are no more neighbours left for vertex ~w, paths are ~w, result is ~w~n", [Source,Paths,Result]),
    Result;

dfs([Neighbour|Other_neighbours],Paths,Result,Graph,Source,Recursion_list,Root) ->
    ?DBG("~w *Current source is ~w~n",[Recursion_list,Source]),
    ?DBG("~w Checking neighbour _~w_ of _~w_, other neighbours are: ~w~n",[Recursion_list,Neighbour,Source,Other_neighbours]),



?    DBG("~w Ready to check for visited: ~w~n",[Recursion_list,Neighbour]),

 case lists:member(Neighbour,Paths) of 
        false ->
            ?DBG("~w Found an unvisited neighbour ~w, path is: ~w~n",[Recursion_list,Neighbour,Paths]),
New_paths = [Neighbour|Paths],
?DBG("~w Added neighbour to paths: ~w~n",[Recursion_list,New_paths]),
ets:insert(Result,{Root,Paths}),

            Neighbours = digraph:out_neighbours(Graph,Neighbour),
            ?DBG("~w The neighbours of the unvisited vertex ~w are ~w, path is: ~w, recursion:~n",[Recursion_list,Neighbour,Neighbours,[Neighbour|Paths]]),
                dfs(Neighbours,New_paths,Result,Graph,Neighbour,[[[]]|Recursion_list],Root);
            true -> 
            ?DBG("~w The neighbour ~w is: already visited, paths: ~w, backtracking to other neighbours:~n",[Recursion_list,Neighbour,Paths]),
ets:insert(Result,{Root,Paths})

end,

        dfs(Other_neighbours,Paths,Result,Graph,Source,Recursion_list,Root).

任何想法,以运行,这可接受的时间?

有帮助吗?

解决方案

编辑: 好的我现在明白了,你想要找所有的简单途径从顶点中向图。这样一个深入的先搜索与回溯将是合适的,因为你已经实现。总的想法是去到一个邻国,然后转到另一个人(不你已经访问),并保持下去,直到你撞上了一条死胡同。然后回溯到的最后一个顶点,你是在和选择不同的邻居,等等。你需要获得繁琐位的权利,但它不应该太难。E.g。在每一个步骤,你需要签在顶点'的探讨'或'未开发的'取决于你是否已经访问了他们。性能不应该是一个问题,适当地实施的算法应该采取可能O(n^2)的时间。所以我不知道你什么都做错了,或许你正在访问太多的邻居吗E.g。也许你重新审视的邻居,你已经访问,并会圆圈或什么东西。

我还没有真阅读你的程序,但Wiki网页上的深度第一次搜索都有一个简短、简单伪程序的你可以试图复制在你的语言。储存的图表,作为邻接名单,以使它更加容易。

编辑: 是的,对不起,你是对的,标准的外勤部的搜索将不会的工作,因为它代表,则需要它调整略,以便不会重新讨论的顶点,它已经访问之前。所以你被允许访问的任何折点,除了那些你已经存在您目前的道路。这当然意味着我的运行时间是完全错误的,复杂的算法将通过屋顶。如果平均的复杂性的图表是d+1,然后将有大约d*d*d*...*d=d^n可能的路径。因此,即使每一个顶点只有3个邻国,仍有相当多的道路,当你得到上述20顶点。有没有办法解决,是真的,因为如果你想要你的程序出所有可能的路径,然后事实上你会需要输出的所有d^n他们。

我有兴趣知道是否你需要这个一个特定的任务,或是只是想这个程序的兴趣。如果是后者,你就只能快乐小,偶尔连接的图表。

其他提示

我不明白问题。如果我有图G=(V,E)=({A,B},{(A,B),(B,A)}),则有从A到B的无限路径{[A,B],[ A,B,A,B],[A,B,A,B,A,B],...}。如何找到循环图中任何顶点的所有可能路径?

编辑:

您是否尝试过计算或猜测某些图形可能的路径?如果您已完全连接图形,则将获得

  • 2-1-
  • 3-4
  • 4-15
  • 5-64
  • 6-325
  • 7-1956
  • 8-13699
  • 9-109600
  • 10-986409
  • 11-9864100
  • 12-108505111
  • 13-1302061344
  • 14-16926797485
  • 15-236975164804
  • 16-3554627472075
  • 17-56874039553216
  • 18-966858672404689
  • 19-17403456103284420
  • 20-330665665962403999

    确定要查找所有节点的所有路径吗?这意味着,如果在一秒钟内计算一百万条路径,则要计算到20个完全连接图中的所有节点的所有路径,将花费10750年。它是您任务的上限,所以我认为您不愿意这样做。我想你还想要其他东西。

无论如何都不是一种改进的算法解决方案,但是您通常可以通过产生多个工作线程来提高性能,这里可能每个第一级节点都有一个工作线程,然后聚合结果。这通常可以相对轻松地改进朴素的蛮力算法。

您可以在此处看到示例:某些Erlang矩阵函数,在maximise_assignment函数中(注释从今天的第191行开始)。再说一次,底层的算法还相当幼稚和蛮力,但是对于许多形式的矩阵,并行化可以很好地提高它的速度。

过去,我曾使用类似的方法来查找图中的汉密尔顿路径数。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top