【问题标题】:Randomized algorithm for finding hamiltonian path in a directed graph在有向图中寻找哈密顿路径的随机算法
【发布时间】:2010-12-31 12:37:21
【问题描述】:

来自这篇维基百科文章:

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 的所有内容。

【问题讨论】:

  • 哈密顿路径存在于无向图上(根据定义)。任何找到它们的算法都必须因此在无向图上运行。
  • 嗯,维基百科的文章说:“哈密顿路径问题和哈密顿圈问题是确定给定图中(无论是有向还是无向)中是否存在哈密顿路径或哈密顿圈的问题。”基本上,我正在寻找在有向图中可以找到的最长的简单路径(没有多次访问的顶点)。现在看来这个算法帮不了我了。
  • 维基百科中的不一致:“......哈密顿路径(或可追踪路径)是无向图中的路径,它只访问每个顶点一次。哈密顿循环(或哈密顿循环)是一个循环在一个无向图中,每个顶点只访问一次......"。
  • 经过进一步思考,该算法可能仍然适用于有向图。考虑到顶点A 的邻居的概念被解释为“所有顶点X,其中存在一条边A -> X”。
  • 对,但是我们如何实现FindEnd,正如您在伪代码中所说的那样?请参阅我的编辑 2。

标签: algorithm language-agnostic random graph


【解决方案1】:

这确实是一个很不清楚的解释,而且算法似乎也不是来自任何列出的参考文献。

这个想法似乎是首先通过随机选择初始节点来创建一条随机路径,然后通过尽可能长的时间选择随机邻居来继续。当无法选择更多邻居时,路径要么是哈密顿路径,要么不是。如果不是,则路径上的最后一个节点在路径上已经有一些邻居(见下文),因此旋转意味着从最后一个节点到路径上已经存在的邻居创建一条边,并从路径中删除一个链接为路径选择的邻居。然后,路径有一个新的终点,过程将从该终点继续。

这个算法似乎假设,例如,没有只有一条边的节点。但是,这些很容易涵盖:如果有一个,就从那个开始,如果有两个,从其中一个开始并尝试在另一个结束,如果有两个以上,则不能哈密​​顿路径。

【讨论】:

    【解决方案2】:

    基本上,一旦您随机选择的节点以这样一种方式构建了一个图,即最后一个顶点 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
        }
      }
    

    【讨论】:

    • RemoveRandomEdgeFrom(next, path); DrawEdgeTo(next, current, path); 可能会导致循环。您不能随意删除边缘。您必须删除最接近current 的边缘。
    • 我接受这个答案,因为伪代码有助于理解算法,尽管我们发现它只适用于无向图。
    【解决方案3】:

    你了解什么是边缘吗?如果顶点是 v1, v2, .. vn,那么边是一对 (v1, v2) - 想象在 v1 和 v2 之间画一条线,这就是边。

    所以,基本上你会执行一个基本的爬山算法(不断添加边并访问未访问的节点),但要遵守你不会多次访问节点的约束。

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-11-12
      • 1970-01-01
      • 2011-07-17
      • 1970-01-01
      • 2018-08-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多