在有向图中求哈密顿路径的随机算法

时间:2009-12-31 21:32:31

标签: algorithm language-agnostic random graph

来自这篇维基百科的文章:

http://en.wikipedia.org/wiki/Hamiltonian_path_problem

  

哈密顿量的随机算法   在大多数图表上快速的路径是   以下内容:从随机开始   顶点,如果有则继续   邻居没去过。如果没有   更多未经访问的邻居和路径   形成不是汉密尔顿主义者,选择一个   邻居均匀随意,和   使用该邻居作为枢轴旋转。   (也就是说,为此添加一个优势   邻居,并删除其中一个   来自那个邻居的现有边缘   不要形成循环。)然后,继续   新的算法在新的结束   路径。

我不太明白这个旋转过程应该如何工作。有人可以更详细地解释这个算法吗?也许我们最终可以用更清晰的描述更新Wiki文章。

编辑1:我想我现在理解这个算法,但它似乎只适用于无向图。任何人都可以确认吗?

这就是为什么我认为它只适用于无向图:

alt text http://www.michaelfogleman.com/static/images/graph.png

假装顶点的编号如下:

123
456
789

让我们说我到目前为止的路径是:9, 5, 4, 7, 8。所有8个邻居都被访问过。假设我选择5来删除边缘。如果我删除(9,5),我最后创建一个循环:5, 4, 7, 8, 5,所以我似乎必须删除(5,4)并创建(8,5)。如果图是无向的,那很好,现在我的路径是9,5,8,7,4。但是如果你想象那些边被定向,那不一定是有效路径,因为(8,5)是边但是( 5,8)可能不是。

编辑2:我想对于有向图我可以创建(8,5)连接然后让新路径只是4, 7, 8, 5,但这似乎适得其反必须砍掉以前导致顶点5的所有东西。

3 个答案:

答案 0 :(得分:5)

这确实是一个非常不清楚的解释,并且该算法似乎也没有来自任何列出的参考文献。

这个想法似乎是首先通过随机选择初始节点来制作随机路径,然后通过选择随机邻居来进行,只要可能就行。当不能再挑选邻居时,要么路径是汉密尔顿,要么不是。如果不是,则路径上的最后一个节点已经在路径上有一些邻居(见下文),因此,旋转意味着从最后一个节点到已经在路径上的邻居边缘并从中删除其中一个链接已被选为路径的邻居。然后,路径有了一个新的结束,继续进行该过程。

例如,该算法似乎假定没有只有一条边的节点。但是这些很容易掩盖:如果有其中一个,那么就从它开始,如果有两个,从其中一个开始并尝试最终到另一个,如果有两个以上,则不能汉密尔顿主义的道路。

答案 1 :(得分:4)

基本上,一旦你的随机选择的节点构造了一个图形,使得最后一个顶点A没有未访问的相邻顶点,你需要使一个顶点可以继续。

要做到这一点:随机选择一个相邻顶点,删除其现有边之一(在哈密顿路径中,任何一个顶点只能有两条边),然后从当前顶点绘制一条新边,现在可用随机选择一个。然后,您可以从随机选择的顶点到图形的末尾(只有一条边缘离开它的第一个顶点)进行跟踪并继续算法。

各种可怕的假代码:

  Graph graph;
  Vertex current;
  Path path;

  while(!IsHamiltonian(path))
  {
    if(HasUnvisitedNeighbor(current, path))
    {
      Vertex next = SelectRandomUnvisited(current, path);
      DrawEdgeTo(next, current, path);
      current= next;
    }
    else
    {
       Vertex next = SelectRandomNeighbor(current, path);
       RemoveRandomEdgeFrom(next, path);
       DrawEdgeTo(next, current, path);
       path = FindEnd(next, current, path);  //Finds the end of the path, starting from next, without passing through current
    }
  }

答案 2 :(得分:1)

你明白什么是优势?如果顶点是v1,v2,.. vn,那么边是一对(v1,v2) - 想象一下在v1和v2之间画一条线,那就是边。

所以,基本上你做了一个基本的爬山算法(不断添加边缘和访问未访问的节点),但要受到不多次访问节点的限制。

如果你发现你不能再继续(无法从当前顶点到达任何未访问的节点),那么你选择一个连接的随机顶点(该顶点和一个之间有一条边)你已经访问过的顶点的数量)并在该顶点和尚未在路径中的被访问节点之间添加一条边。

这可能(并且可能必须留给数学家)创建一个循环。您可以通过从路径中的边缘移除另一条边来移除循环。

基本上,这是一种爬山算法,当你遇到困难时会有一些随机扰动。当你遇到困难时,你基本上添加另一个边缘并从图表中删除一个并尝试继续。如果你完全错了,你仍然可以找到一个解决方案,因为理论上你可以添加所有正确的边缘并删除所有原始的错误选择。