找到所有可能的路径,从一个顶点,在针对循环中的曲线图二郎
-
27-10-2019 - |
题
我想要实现的功能找到所有可能的路径,以所有可能的折点的一个来源的顶点V在针对循环图G
性能现在不要紧,我只是想了解的算法。我已经阅读的定义深先搜索算法,但是我没有完全理解要做什么。
我没有任何已完成的代码,以提供这里,因为我不知道该如何:
- 结果存储(与一个->B>C->我们还应该商店一个->B和A->B>C);
- 代表的图表(图?清单元组?);
- 多少递归来使用(工作与每个相邻的顶点?).
我怎么能找到所有可能的路径,形成一个特定来源的顶点,在针对循环中的曲线图二郎?
UPD:基于答案,所以到目前为止,我已经重新定义的曲线定义:这是一个非环曲线图。我知道,如果我递归功能命周期是无限的循环。为了避免这种情况,我只能检查,如果当前的顶点是在该列表中所得到的路-如果是的话,我停止遍和返回的路径。
UPD2: 谢谢你的发人深省的意见!是的,我需要找到简单的所有道路,没有从循环的一个来源的顶点到所有其他人。
在一个曲线图这样的:
与源顶点的一种算法应该找到下面的路径:
- 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行开始)。再说一次,底层的算法还相当幼稚和蛮力,但是对于许多形式的矩阵,并行化可以很好地提高它的速度。