【问题标题】:How to find path of exact length in graph如何在图中找到精确长度的路径
【发布时间】:2012-06-08 12:12:59
【问题描述】:

我想在无向图中找到固定长度的路径(在运行程序时给出)。我正在使用我的图形的邻接矩阵。
我尝试使用一些算法,如 DFS 或 A*,但它们只返回最短路径。

无法再次访问节点。

假设我的图有 9 个节点,最短路径是由 4 个节点构建的。
我想要有一个额外的变量来“告诉”算法我想要找到有 7 个节点的路径(例如),它将返回包含在我的预期路径 {1,2,4,5,6, 7,8}.
当然,如果没有我想要的路径解决方案,它不会返回任何内容(或者它会返回接近我预期的路径,比如说 19 而不是 20)。

有人告诉我关于带有回溯的 DFS,但我对此一无所知。
有人可以解释如何使用带有回溯的 DFS 或推荐一些其他算法来解决这个问题吗?

【问题讨论】:

  • “接近我期望的路径” - 这是模糊的。

标签: algorithm graph-algorithm path-finding


【解决方案1】:

假设您可以在图中找到长度为 d 的路径,那么您可以运行此算法 |V|次并找到最长的 NP 完全路径。所以你可以尝试以下方法 -

1) 近似算法 2)蛮力方法(更适合编程)。使用 GPU 加速您的代码。

您可能也会感兴趣 -

DAG 存在线性时间算法。

【讨论】:

    【解决方案2】:

    单个 dfs 应该就足够了:

    void dfs(int start, int hops)
    {
      if(hops == k && start == t)
        {
          path++;
          return;
        }
      else if(hops >= k)
        return;
      for(int w = 1; w <= n; w++)
        if(routes[start][w])
          dfs(w, hops + 1);
    }
    

    这里,k是路径的长度,routes[][]是图的邻接矩阵。 path 是一个全局变量。这可以考虑循环 - 它考虑了给定长度的所有路径。从 main 调用

    path = 0;
    dfs(source, k);
    cout<<path;
    

    请注意,节点数比跳数多一。另请注意,如果路径的长度很大,则此功能会快速叠加。没有双关语。

    【讨论】:

    • 在DFS中,n是节点数,k是我想要的路径长度,t是结束节点,对吧?
    • 哎呀,对不起。我没有意识到你需要实际的路径......这只会给你路径的数量。 :P
    【解决方案3】:

    回溯确实是一个合理的解决方案。这个想法是递归地找到所需长度的路径。

    伪代码:

    DFS(depth,v,path):
      if (depth == 0 && v is target): //stop clause for successful branch
           print path
           return
      if (depth == 0): //stop clause for non successful branch
           return
      for each vertex u such that (v,u) is an edge:
           path.append(v) //add the current vertex to the path
           DFS(depth-1,u,path) //recursively check all paths for of shorter depth
           path.removeLast() // clean up environment
    

    上述算法将生成所需深度的所有条路径。
    使用DFS(depth,source,[]) 调用(其中[] 是一个空列表)。

    注意:

    • 算法将生成可能不简单的路径。如果您只需要简单的路径 - 您还需要维护 visited 集,并在将每个顶点附加到找到的路径时添加它,并在将其从路径中删除时将其删除。
    • 如果您只想找到一个这样的路径 - 您应该从函数返回值(如果找到这样的路径,则返回 true),并在返回值为 true 时中断循环(并返回 true)。

    【讨论】:

    • 我试图用 Java 制作你的伪代码,但出了点问题,我不知道是什么:pastebin.com/60u3FYmf 其中 adj[][] 是我的图形和路径的邻接矩阵存储在堆栈。
    • 好吧,不能确定,但​​从第一眼看:(1)你为什么从 1 迭代到 numVertex (包括)而不是 0 到 numVertex-1 (包括)? java中的数组是基于0的。 (2) 递归调用后似乎错过了visited.pop(),所以visited 集合正在被填充,但在你用尽某个路径后,元素永远不会被取出。 (3) depth == 0 &amp;&amp; v is not target 应该有另一个停止子句(我在伪代码中也错过了,将很快编辑) - 它应该终止这个分支。
    • 我有这样的图表(现在我正在测试这个):i.imgur.com/SWu09.jpg .. 当我给出深度 8 并开始 1 结束 9 (1,9) 时,DFS 什么也没有显示。它应该写成 [1,2,3,6,5,4,7,8,9] 或 [1,4,7,8,5,2,3,6,9]。当我给出深度 3 并开始 1 结束 2 (1,2) 时,它正确地写入 [1,4,5,2],但是当我将深度更改为 5 时 - 什么都没有。它应该至少给出 [1,4,7,8,5,2]。我不知道这里出了什么问题:pastebin.com/CQpwfkg1
    【解决方案4】:

    上述问题是NP完全的。你可以轻松解决Hamiltonian Cycle Problem,给定一个有效的算法来解决你的问题。

    因此,不存在多项式时间解(除非 P=NP)。如需详尽的搜索、指数时间解决方案,请查看@amit 的答案。

    【讨论】:

      【解决方案5】:

      尝试找到最长的路径,然后将其切割成所需的长度。最长的路径也称为图的直径。对每个顶点运行 DFS 可以找到最长的路径。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-06-01
        • 2022-01-19
        • 1970-01-01
        • 2023-03-09
        • 1970-01-01
        • 2022-11-10
        相关资源
        最近更新 更多