为什么不能使用DFS在未加权图中查找最短路径?


16

我了解按原样使用DFS不会在未加权图中找到最短路径。

但是,为什么要对DFS进行调整,以使其能够在未加权图中找到最短路径,却前景如此?关于该主题的所有文字都简单地指出无法完成。我不敢相信(自己没有尝试过)。

您是否知道允许DFS在未加权图中找到最短路径的任何修改?如果不是,那么使它变得如此困难的算法又是什么呢?


1
在非加权图上最常见的寻路算法是A *,稍加修改即使结点更接近终点。这将提供类似于DFS的算法,因为它将首先尝试最直接的路由,并且仅在需要时向外冒泡。
BlueRaja-Danny Pflughoeft 2012年

1
尝试在某些(精选)图上使用DFS;如果确实不起作用,则应该遇到问题。顺便说一句,您的问题看起来像是在加权图上起作用。
拉斐尔

是的,您可以做到。这是解决方案
Anmol Middha

Answers:


12

您调整的深度优先搜索的唯一元素是调查孩子的顺序。普通版本以任意顺序进行,即以存储子级的顺序进行。

我能想到的唯一可行的替代方法(朝最短路径)是一种贪婪的方法,即按照孩子到当前节点的距离(从小到大)的顺序查看它们。为此规则构造一个反例很容易:

贪婪规则的反例
[ 来源 ]

现在,没有证据表明不存在选择下一个要调查的孩子的策略,这将使DFS查找最短路径。

但是,无论规则¹如何,您都可以构造具有DFS的图,使其在第一个节点处进行长时间的绕行,就像我对贪婪规则所做的那样。分配边缘和的权重,使得该规则选择访问第一,并分配的重量大于所述一个。因此,DFS永远找不到最短路径(在一般图中)似乎是合理的。s a a a b s t (s,t)(s,a)a(a,b)(s,t)

请注意,由于您可以将每个(正整数)加权图表示为未加权图-只需将具有成本边替换为具有节点的链-相同的示例处理未加权图上的DFS。在这里,情况实际上更加严峻:如果没有权重,DFS可以用什么来确定下一个要拜访的孩子?c 1cc1


  1. 只要规则是确定性的。如果不是这样,显然不能总是找到最短的路径。

如果我错了,请纠正我,但这是否意味着DFS可以在任何图中找到最短路径,但是这样做会花费指数时间?
Anmol Singh Jaggi'2

@AnmolSinghJaggi否。DFS仅找到一条路径。
拉斐尔

10

广度优先搜索是一种算法,它将在未加权图中找到最短路径。

从DFS到算法可以进行简单的调整,该算法将在未加权图上找到最短路径。本质上,您将DFS使用的堆栈替换为队列。但是,生成的算法不再称为DFS。相反,您将实现广度优先搜索。

上一段给出了正确的直觉,但是稍微简化了这种情况。编写简单交换确实可以实现广度优先搜索的代码很容易,但是起初看起来像是正确的实现但实际上不是这样的代码也很容易。您可以在此处找到有关BFS与DFS的 cs.SE相关问题。您可以在此处找到一些不错的伪代码。


3

您可以!!!

在深入时将节点标记为已访问,在返回时取消标记,而在发现另一个分支时返回则重复相同。

为找到目标节点的所有可能的搜索保存成本/路径,比较所有此类成本/路径并选择最短的成本/路径。

这种方法最大的问题(我的意思是BIG)是您将多次访问同一节点,这使得dfs成为最短路径算法的明显错误选择。


1
您可能需要注意,这极大地改变了复杂性。如果我正确理解的话,这将有可能探索从到所有可能路径。Ťst
ryan

1
@ user2407394您是否实际实现了DFS的这种变体一次并针对中等大小的图形正确运行了它?我会犹豫将此变化称为DFS。我将其称为深度优先路径穷举搜索。
John L.

我已经实施了这种方法,但它的工作速度非常慢。我正在考虑添加助记符以提高性能。
麦克风

@ user2407394似乎可以使用,但是如果您都未标记,那么如何检查何时停止,因为没有“已访问”列表?
乔·布莱克

0

BFS具有一个很好的属性,它将检查从根到边的所有边缘,并保持从根到其他节点的距离尽可能小,但是dfs只是跳到第一个相邻节点并沿深度方向移动。您可以修改DFS以获得最短的路径,但是您最终只会得到时间复杂度更高的算法,或者最终会完成BFS所做的相同操作



-3

您可以

只是以dfs方式遍历图形并检查

if(distance[dest] > distance[source]+cost[source_to_destination]){
    distance[dest] = distance[source] + cost[source_to_destination]);
}

这是完整解决方案的链接


1
接受的答案声称这是不可能的,这与您的主张相矛盾。您能否解释为什么您认为此方法仍然有效?(或解释为什么这种方法总体
离散蜥蜴

难道这不只是重复user2407394的答案,而只是用难以理解的代码(您尚未定义任何这些变量的含义,对我而言并不明显)而不是进行解释吗?
David Richerby

是的,它是user2407394的答案的实现。对造成的不便表示歉意。我在代码中添加了注释。您现在可以检查它。
Anmol Middha
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.