找到遍历图中所有顶点的路线的更好算法是啥?

Posted

技术标签:

【中文标题】找到遍历图中所有顶点的路线的更好算法是啥?【英文标题】:What is a better algorithm for finding routes that traverse all vertices in a graph?找到遍历图中所有顶点的路线的更好算法是什么? 【发布时间】:2013-01-09 23:25:52 【问题描述】:

所以我有以下问题:

给定一个 x x y 维度的网格,计算路线的数量 通过它从一个角落开始(比如说左上角)并结束于 另一个(右下)并通过每个顶点。

所以我目前的方法只是通过尝试所有可能的路径并计算到达终点并遍历每个节点的路径来强制它。虽然它有效,但它是 O(n^2) 并且非常快地变得令人难以置信的慢。由于路径需要遍历每个顶点,我不确定如何组合。

我查找了更复杂的算法,Hierholzer 计算欧拉路径的算法似乎有些相关但并不完美,因为为此不能多次遍历节点。

事实上,我的程序可以运行,但效果很差,我想让它更有效率。我可以使用更好的算法吗?

编辑感谢到目前为止的回答。澄清一下,二维网格中的所有节点都通过 n/e/s/w 连接

此外,网格不必是正方形

【问题讨论】:

这不是旅行商问题吗?如果是这样,回答的人不仅能得到几分,还能获得诺贝尔奖! 如果它“非常快地变得难以置信地慢”,那么它不是O(n^2) @Jan Dvorak 是的,我认为暴力破解是次要的 @ccleve 这不是 TSP。 TSP 是指您最小化行驶的总距离,而不是简单地计算路径的数量。 修改后,这只是一个有最终答案的数学问题,不需要使用遍历/等。只需在表达式中插入 x 的值即可计算 【参考方案1】:

您无能为力,因为它是Hamiltonian path problem,它是NP-complete。

但是,您可能实际上会搜索其他内容并为您尝试解决的问题添加一些限制...

编辑:

正如@JanDvorak 所说,您的具体限制是您使用的是方形网格。到目前为止我的发现:

如果x 是偶数,则无法遍历从左上角开始到右下角结束的所有顶点。证明:

让我们计算沿轴的定向运动,例如上是-1,下是1,左是-1,右是-1。因此,拥有 x x x 网格,您的总移动量将是 2*x。在每个顶点(除了最后一个!)您只选择一个方向。因此,如果您需要通过偶数个顶点,那么您的总运动将是偶数,反之亦然。如果x 是偶数,则顶点数为奇数,但总移动仍然是偶数 => 你找不到任何方法。

【讨论】:

你知道图表是一个网格。这不是简化了一些事情吗? @JanDvorak,是的,你可能是对的,我现在正在考虑。 我明白了。在这种情况下,拐角仅用于示例目的(我正在寻找适用于 2 个拐角的任意组合的方法),但这在对角线的情况下绝对有帮助。如果起点和终点在同一侧怎么办? @CharmQuark,好吧,你需要检查一下,“总移动”和可通过顶点的数量是否相同模 2(例如除法余数相同)。如果不是这样 => 肯定没有路径。 @JanDvorak,当然。顺便说一句,有一个方形网格有问题。但是,如果 OP 可以显示一些数字,它可能可能更容易猜出正确的公式并证明它。【参考方案2】:

首先,如果 x 是偶数,则有一个简单的奇偶校验参数表明答案始终为零;检查网格并注意左上角和右下角的正方形颜色相同,并且不能同时访问第一个和第 n2th 个颜色,因为 n2 是即使 1 是奇数。

如果 x 是奇数,我不知道如何计算路径,但请注意总数至少呈指数级增长:n*n 网格的任何遍历都可以提升为 (n +2)*(n+2) 网格。沿着第一行向右,沿着第二行向左,沿着第一列向下,沿着第二列向上,然后在剩余的方格上进行 n*n 网格遍历,您可以得到一个;您可以通过以相反的顺序覆盖前两行和两列来获得另一个。

这应该告诉您,蛮力解决方案不太可能很好地工作。

【讨论】:

【参考方案3】:

本学期我在一个主题上处理过这样的问题。 我想你可以看看我们这样的元启发式算法:

Tabu Search Evolutionary Computation

你可能想保持蛮力,除非你真的需要改进;因为它们非常复杂。

【讨论】:

以上是关于找到遍历图中所有顶点的路线的更好算法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

在无向图中通过其顶点找到一条边 [C++ BGL]

1762: 图的遍历——深度优先搜索

用邻接表表示图进行深度优先遍历时,通常采用()来实现算法

图的遍历

断开图中的所有顶点 - 算法

常用的图算法:深度优先(DFS)