【问题标题】:shortest path connecting certain nodes in an undirected graph连接无向图中某些节点的最短路径
【发布时间】:2012-10-02 18:56:47
【问题描述】:

我有一个无向和未加权图的某个节点子集。我正在尝试确定所有这些节点之间是否存在路径,如果存在,最短路径是什么,其中包含不在节点子集中的最少节点。

我一直在想办法修改最小生成树算法来实现这一点,但到目前为止我还没有想出一个可行的解决方案。

有没有好的方法可以做到这一点,或者这是对已知算法的描述?

【问题讨论】:

    标签: c# algorithm graph


    【解决方案1】:

    我创建了一个 Graph/Node/Connection 类,它不仅可以显示最短路径,还可以告诉你是否所有节点都已连接:

    var allNodesAreConnected = StartNode.AllNodes.All(n => n.IsConnectedToStartNode);
    

    或者如果您想知道哪些节点未连接,请稍微更改一下:

    var anotConnectedNodes = StartNode.AllNodes.Where(n => !n.IsConnectedToStartNode);
    

    这篇文章中有更多示例和完整代码: Create your own navigation system (with a Graph, Node and Connection class)

    【讨论】:

      【解决方案2】:

      对于没有图论背景的人,我已经解决了这个问题,发现在未加权无向图中,最简单的方法是Depth First Search。 Dijkstra 等算法的实现通常采用加权解决方案,并为权重输入任意值。

      我发现可行的解决方案我在使用DFS时遍历了节点并记录了每一个成功的旅程,那么这只是一个返回最短成功旅程的案例。

      这是完成繁重工作的文件: Depth First Search Algorithm

      【讨论】:

        【解决方案3】:

        这里有一个方法可以帮助你:

        使用Floyd-Warshall 或 Dijkstra 求每个 i 和 j 的节点 i 和节点 j 之间的距离 d(i, j),使得节点 i 和节点 j 在节点的子集中。

        (如果 d(i,j) = infinity 那么现在停止,没有解决方案)

        制作一个包含子集中每个节点的新图。对于每个 d(i, j),在新图中的节点 i、节点 j 之间添加一条边,权重 = d(i, j)

        现在在这个新图上使用旅行商算法来找到访问所有节点的最短路径。

        这条最短路径为您提供路径的长度,但该路径可能会多次访问某些节点。这意味着我们对所需子集之外的节点数量有一个上限。

        【讨论】:

        • 感谢您的回复。你介意更详细地了解它是如何工作的吗?在为子集中的每个节点创建新图的第二步中,连接子集中的节点但不属于子集的其他节点应该发生什么?
        • 我刚刚意识到我的方法获得了路径的长度,而不是其中的节点。为了澄清,d(i, j) 是 nodei 和 nodej 之间不在子集中的节点数。 i,j 之间的边表示这条路径(但我们不关心路径中的那些节点,因此将其表示为一条边)。然后你得到最小生成树。这为您提供了最短路径的长度。但是它并没有告诉你路径在哪里。现在由您来找到一条使子集外节点重叠最大化的路径..
        • 最小生成树会给出每个顶点的路径,而不是访问所有顶点的单一路径。我不认为他在追求什么:(I am trying to determine whether there is a path between all of these nodes)。这个问题实际上是 NP-Hard。
        • 是的。我编辑了我的答案。不知道为什么我提到 MST 而不是 TSP。您可以使用 MST 来估计 TSP 的答案,该答案在最优解的两倍以内。
        • 我看不出有继续讨论的理由——重点很清楚,人们应该明白他在寻找什么。如果您试图最小化不在子集中的节点数量,或者它只是一个次要标准。 cmets 的讨论提供了足够的信息,IMO 可以理解这个问题并得出结论。 (如果是后者,解决方案至少应该是一个很好的开始,当然假设您可以接受非简单路径)
        【解决方案4】:

        您应该使用Dijkstra's shortest path algorithm。首先,您必须为图中的所有边分配权重(或距离),连接不在子集中的两个节点的每条边必须被赋予权重 1。连接子集中一个或两个节点的每条边必须被赋予无限重量。其次,您应该在结果图上运行 Dijkstra 算法。 该算法将检查图的每条边。

        另外,您可以使用A* (A-star) algorithm

        更新: 起初我不明白这个问题。正如@amit 所说,这是一个 NP 难题,是 HCP 和 TSP 的组合。也许某种随机搜索算法可以在多项式时间内以高概率解决这个问题。

        【讨论】:

        • 两者都是到单个顶点的最短路径,对路径没有限制(最短除外)。它不能解决I am trying to determine whether there is a path between all of these nodes
        【解决方案5】:

        我正在尝试确定所有这些之间是否存在路径 节点

        (据我了解,您正在寻找访问所有标记节点的单一路径)

        我的朋友,这可能是个问题 - 您正在描述 Traveling Salesman ProblemHamiltonian Path Problem 的变体(如果您正在寻找简单路径reduction 来自哈密​​顿路径是直截了当的:标记所有节点)。
        但恐怕这些问题是NP-Hard

        NP-Hard 问题是一个我们不知道任何多项式时间解决方案来解决它的问题,并且一般假设是 - 一个不存在1支持>.

        因此,您最好的选择可能是某种指数解决方案。使用动态编程的 TSP 有O(n^2 * 2^n) 解决方案,或者是O(n!) 的蛮力解决方案


        (1) 确实不是一个正式的定义,但这是足够的信息来理解问题,NP-Hard 问题确实还有很多。

        【讨论】:

        • 我同意“标记所有节点”。如果存在长度为 n-1 的路径,则为了最小化最短路径,它是哈密顿路径。
        【解决方案6】:

        Dijkstra 算法或使用广度优先搜索。

        【讨论】:

        • 无法解决:I am trying to determine whether there is a path between all of these nodes
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-07-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-20
        • 1970-01-01
        相关资源
        最近更新 更多