寻找特定顶点最短路径的好算法

2023-12-13

我正在解决下面描述的问题,并且想不出比尝试每个组的每个顶点的每个排列更好的算法。

我得到了一张顶点图,以及一组特定顶点组的列表,目标是找到从特定起始顶点到特定结束顶点的最短路径,并且该路径必须从每个顶点至少经过一个顶点指定的顶点组。 图中还存在不属于任何给定组的顶点。 重新访问顶点和边是可能的。

图形数据指定如下:

  • 顶点列表 - 每个顶点由序列号标识(0 到顶点数 -1 )
  • 边列表 - 顶点对列表(按顶点编号)
  • 顶点组列表 - 向量数列表的列表
  • 特定的起始和结束顶点。

我将不胜感激任何更好的解决方案的想法,谢谢。


Summary:

我们可以使用位掩码来有效地检查到目前为止我们访问过哪些组,并将其与传统的 BFS/Dijkstra 的最短路径算法相结合。

如果我们假设E edges, V顶点,和K必须包含的顶点组,以下算法的时间复杂度为O((V + E) * 2^K)以及空间复杂度为O(V * 2^K)。指数2^K术语意味着它只适用于相对较小的K,比如说最多 10 或 20。

Details:

首先,边缘是否加权?

如果是,那么“最短路径”算法通常是以下算法的变体迪杰斯特拉算法,其中我们保留最短路径的(最小)优先级队列。我们只访问位于队列顶部的节点,这意味着这必须是到达该节点的最短路径。到该节点的任何其他较短路径都已被添加到优先级队列中,并且将出现在当前迭代之前。 (注意:这不适用于负路径)。

如果不是,意味着所有边具有相同的权重,则无需维护具有最短边的优先级队列。我们可以只运行常规的广度优先搜索(BFS),其中我们维护一个包含当前深度的所有节点的双端队列。在每一步中,我们都会迭代当前深度的所有节点(从双端队列的左侧弹出它们),对于每个节点,我们将所有尚未访问的邻居添加到双端队列的右侧,形成下一个级别。

下面的算法适用于 BFS 和 Dijkstra 算法,但为了简单起见,对于答案的其余部分,我将假设边缘具有正权重,并且我们将使用 Dijkstra 算法。但重要的是,对于任何一种算法,我们都只会“访问”或“探索”一个节点,以获得一条必须是到该节点的最短路径的路径。这个属性对于算法的高效至关重要,因为我们知道我们最多会访问每个V节点和E仅边缘一次,给我们一个时间复杂度 of O(V + E)。如果我们使用 Dijkstra,我们必须将其乘以log(V)对于优先级队列的使用(这也适用于摘要中提到的时间复杂度)。

我们的问题

在我们的例子中,我们有额外的复杂性K顶点组,对于每个顶点组,我们的最短路径必须包含至少一个其中的节点。这是一个大问题,因为它破坏了我们简单地遵循“最短当前路径”的能力。

例如,参见这个简单的图表。符号:--表示边缘,start是起始节点,并且end是结束节点。有值的顶点0没有顶点组和具有值的顶点>= 1属于该索引的顶点组。

end -- 0 -- 2 -- start -- 1 -- 2

显然,最优路径首先会向右移动到组内节点1,然后向左移动直至结束。但这对于我们上面介绍的BFS和Dijkstra算法来说是不可能做到的!当我们从开始向右移动以捕获组中的节点后1,我们永远不会向左回到起点,因为我们已经用更短的路径到达了那里。

伎俩

在上面的例子中,如果右侧看起来像start -- 0 -- 0, where 0意味着该顶点不属于一个组,那么去那里并返回起点是没有用的。

尽管路会变得更长,但去那里再回来是有意义的,决定性的原因是其中包括一群我们以前从未见过的人.

我们如何跟踪当前位置是否包含某个组?最有效的解决方案是bit mask。因此,如果我们已经访问了组的一个节点2 and 4,那么位掩码将在该位置设置一个位2 and 4,它的值为2 ^ 2 + 2 ^ 4 == 4 + 16 == 20

在常规 Dijkstra 中,我们只保留一个大小为的一维数组V跟踪到每个顶点的最短路径是什么,初始化为非常高MAX value. array[start]从价值开始0.

我们可以修改此方法以改为具有二维数组[2 ^ K][V], where K是组数。每个值都被初始化为MAX, only array[mask_value_of_start][start]开始于0.

我们存储的值array[mask][node] means 给定已访问过的组,其位掩码值为mask,到达此点的最短路径的长度是多少node?

突然,Dijkstra复活了

一旦我们有了这个结构,我们就可以突然再次使用 Dijkstra 的结构(对于 BFS 来说是一样的)。我们简单地改变一下规则:

  • 在常规 Dijkstra 中,我们永远不会重新访问节点

--> 在我们的修改中,我们通过以下方式区分mask如果某个节点已经被访问过,则永远不会重新访问该特定节点mask.

  • 在常规 Dijkstra 中,当探索一个节点时,我们会查看所有邻居,并且只有在我们设法减少到它们的最短路径时才将它们添加到优先级队列中。

--> 在我们的修改中,我们查看所有邻居,并更新我们用来检查该邻居的掩码,例如:neighbor_mask = mask | (1 << neighbor_group_id)。我们只添加一个{neighbor_mask, neighbor}与优先级队列配对,如果对于特定的array[neighbor_mask][neighbor]我们设法减少了最小路径长度。

  • 在常规 Dijkstra 中,我们只访问具有当前最短路径的未探索节点,保证它是到该节点的最短路径

--> 在我们的修改中,我们只访问各自的节点mask价值尚未探索。我们也只访问所有掩码中当前最短的路径,这意味着对于任何给定的mask它一定是最短路径。

  • 在常规 Dijkstra's 中,我们可以在参观完后返回end节点,因为我们确信我们得到了到达它的最短路径。

--> 在我们的修改中,我们可以在访问后返回end完整的节点mask,表示包含所有组的掩码,因为它必须是完整掩码的最短路径。这就是我们问题的答案。

如果这太慢了...

就是这样!因为时间和空间复杂度与组的数量呈指数关系K,这只适用于非常小的K(当然取决于节点和边的数量)。

如果这对于您的要求来说太慢,那么可能有一个更复杂的算法,更聪明的人可以想出,它可能会涉及动态规划.

这很可能仍然太慢,在这种情况下,您可能需要切换到某些启发式,牺牲准确性以获得更快的速度。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

寻找特定顶点最短路径的好算法 的相关文章

  • 在Python中确定句子中2个单词之间的邻近度

    我需要确定 Python 句子中两个单词之间的接近度 例如 在下面的句子中 the foo and the bar is foo bar 我想确定单词之间的距离foo and bar 确定之间出现的单词数foo and bar 请注意 该词
  • 从对列表创建邻接列表类型结构

    在 C 中 我有 class Pair int val1 int val2 我有一个来自以下来源的配对列表 List
  • 将数字 n 拆分为 k 个不同数字的总和

    我有一个数字 n 我必须将它分成 k 个数字 使得所有 k 个数字都是不同的 k 个数字的总和等于 n 并且 k 最大 例如 如果 n 为 9 则答案应为 1 2 6 如果 n 为 15 则答案应为 1 2 3 4 5 这就是我尝试过的 v
  • 在哪里可以找到有关双三次插值和 Lanczos 重采样的好读物?

    我想用 C 实现上述两种图像重采样算法 双三次和 Lanczos 我知道现有的实现有几十种 但我仍然想制作自己的实现 我之所以这么做 部分原因是我想了解它们是如何工作的 部分原因是我想为它们提供一些主流实现中没有的功能 例如可配置的多 CP
  • 加权图的 BFS 算法 - 寻找最短距离

    我看过很多帖子 即 post1 https stackoverflow com questions 30409493 using bfs for weighted graphs post2 https cs stackexchange co
  • 查找数组中的重叠数据

    我们正在编写一个 C 应用程序 它将有助于删除不必要的数据重复器 只有在以下情况下才可以移除中继器 all它接收到的数据被其他中继器接收 我们第一步需要做的事情解释如下 例如 我有 int 数组的集合 A 1 2 3 4 5 b 2 4 6
  • 递归:n项级数之和

    需要递归函数 系列是 1 2 3 3 4 5 4 5 6 7 递归求 n 的级数之和 我无法想到应该在函数中传递哪些参数 我的方法 我认为我应该传递 n 要相乘的项数 但我无法想到的是我应该如何在同一个函数中 和 以及我的 return 语
  • 查找数组中 2 个缺失数字的最快方法

    这个问题的存在只是出于纯粹的好奇心 不是作业 找到在数组 1 n 中找到两个缺失数字的最快方法 因此 在相关帖子中 查找数字数组中缺失数字的最快方法 https stackoverflow com questions 2113795 qui
  • 大小为 n 的数组,其中一个元素 n/2 次

    给定一个由 n 个整数组成的数组 其中一个元素出现超过 n 2 次 我们需要在线性时间和恒定的额外空间中找到该元素 YAAQ 又一个数组问题 我有一种偷偷的怀疑 这类似于 在 C 中 We don t need an array publi
  • 如何从列中创建对称矩阵?

    例如 我想转动以下列 90 175 600 650 655 660 代入矩阵 90 175 600 650 655 660 175 600 650 655 660 655 600 650 655 660 655 650 650 655 66
  • Python 将字符串组合成尽可能短的字符串?

    如果我有一个字符串列表 我想将它们组合成一个具有重叠字符的字符串 如果没有剩余的重叠字符串 请将其添加到末尾 这是一个过于简化的版本 input one two output twone 我正在寻找一种方法来对输入列表中的任意数量的字符串执
  • 我该如何解决? KnapSack - 值完全相同,但每个对象都有三个权重

    我在解决我的练习时遇到问题 我读到了动态规划和算法 我认为我的练习是 特定背包问题 我用暴力法解决了它 但我无法用动态规划解决它 我有一艘重300吨的船 背包 有些晶体本身含有 3 种物质 X Y Z 每种物质都有重量 并且所有晶体都具有相
  • 单词预测算法

    我确信有一篇关于此问题的帖子 但我找不到提出这个确切问题的帖子 考虑以下 我们有字典可供使用 我们收到了许多单词段落 我希望能够根据此输入预测句子中的下一个单词 假设我们有几个句子 例如 你好 我的名字是汤姆 他的名字是杰瑞 他去了没有水的
  • 具有最小刻度的图表的漂亮标签算法

    我需要手动计算图表的刻度标签和刻度范围 我知道漂亮刻度的 标准 算法 参见 我也知道这个Java实现 http erison blogspot nl 2011 07 algorithm for optimal scaling on char
  • 沿着长数据序列在固定大小的移动窗口中查找中值

    给定一个数据序列 可能有重复项 一个固定大小的移动 窗口 从数据开始处每次迭代时移动窗口 序列 使得 1 从窗口中删除最旧的数据元素并添加新数据 元素被推入窗口 2 求每次移动时窗口内数据的中位数 以下帖子没有帮助 有效地找到随机序列的中值
  • 给定一个零索引数组 & 该数组的平衡索引[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 给出一个由 N 个整数组成的零索引数组 A 该数组的平衡索引是任何整数 P 满足 0 P 例如 考虑以下由 N 8 个元素组成的数组
  • 循环中的递归算法复杂度(运行时间)

    我想了解您对如何检测以下递归算法的 T n 运行时间 的意见 Charm 是一种用于发现事务数据库中频繁闭项集的算法 频繁闭项集列表是在一组交易 tids 中多次出现的频繁项 例如面包和牛奶是经常一起购买的物品 它们是通过将索引为 i 的当
  • 根据位置计算组合

    我在解决这个问题时遇到了麻烦 创建一个函数 给定字符集 C 可以生成第 N 个组合 或者返回给定起始位置 Ns 和结束位置 Ne 以及组合的最大长度 Mx 的一系列组合 一个具体的例子 令 C A B C 我们知道不同的组合将如下所示 假设
  • 对产品列表进行分类的算法? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有一个代表或多或少相同的产品的列表 例如 在下面的列表中 它们都是希捷硬盘 希捷硬盘 500Go 适用于笔记本电脑的希捷硬盘 120
  • 缓存感知树的实现

    I have a tree where every node may have 0 to N children 用例是以下查询 给定指向两个节点的指针 这些节点是否位于树的同一分支内 Examples q 2 7 gt true q 5 4

随机推荐

  • 如何在 Python 中将数据框作为参数传递给 SQL 查询?

    我有一个由一列值组成的数据框 我想将其作为参数传递以执行以下 sql 查询 query SELECT ValueDate Value FROM Table WHERE ID in 所以我尝试了 以及其他许多事情 以下内容 df pd rea
  • 如何将 jQuery 安装到 Nuxt.js 中?

    我试图在我的项目中添加 jQuery 尽管我收到一个错误 指出它未定义 plugins src plugins js svgSprite js mode client src plugins vendor jquery jquery min
  • 仅在提交或用户输入时验证表单字段

    我有使用验证的表单字段required 问题是 呈现表单时会立即显示错误 我希望它仅在用户实际在文本字段中输入或提交后显示 我怎样才能实现这个 Use dirty仅在用户与输入交互后才显示错误的标志 div div
  • string.search() 忽略重音字符?

    我需要将重音字符视为与非重音字符相同 这是我的代码 var re new RegExp string i if target search re 0 它目前忽略字符的大小写 我如何也忽略字符是否重音 我认为你必须先删除重音符号 然后再进行正
  • 如何从排除另一个元素的元素中获取 html() ?

    抱歉问了一个真正愚蠢的问题 但无论哪种方式都不起作用 div class content BEFORE div class dontgrab div div
  • 如何从json字符串中提取值?

    我有一个文件 其中有一堆列和一个名为jsonstring是字符串类型 其中包含 json 字符串 假设格式如下 key1 value1 key2 level2key1 level2value1 level2key2 level2value2
  • Java 大文件上传抛出 java.io.IOException: Map failed

    我正在使用 Spring 和 Hibernate 并尝试上传大文件 但是当我尝试上传时 超过 150 Mb 那么它会生成错误 例如 Caused by java lang OutOfMemoryError Map failed at sun
  • 在准备好的语句中重用匿名参数

    我正在自定义 hibernate 生成的插入 SQL 但遇到了问题 当 Hibernate 自己生成查询时 它会将数据插入表的前两列 但这会导致数据库错误 因为表的所有四列都是不可为空的 为了正确执行插入 必须将相同的数据插入到新记录的两列
  • 在 opencart 中添加“加”“减”代替“添加到购物车”

    我想用 OpenCart 2 0 1 1 中的 2 个加号和减号按钮替换添加到购物车 现在我无法正确编码减号按钮 我在中添加了加号和减号按钮catalog view theme template module featured tpl并拨打
  • C++ 图像处理库

    我需要一个可以检测图像中的对象的库 使用边缘检测 这与验证码无关 我正在开发一个使用 OCR 且可以在任何屏幕分辨率下工作的 MTGO 机器人 为了使其能够移植到任何屏幕分辨率 我的想法是扫描结果页面上的狭窄范围 玩家拥有的卡牌可以在文本行
  • 转换二维数组

    What is selectMany ToArray 方法 它是一个内置方法吗C 我需要将二维数组转换为一维数组 如果你的意思是jagged array T SelectMany是你的朋友 但是 如果您的意思是矩形的 array T 那么你
  • Android 浏览器上未引发 JavaScript 按键事件

    我创建了一个简单的代码来处理keypress event var counter 0 input on keypress function div text key pressed counter JSFiddle 但移动浏览器 Andro
  • 如何将 html 链接添加到图像标题

    我实际上需要在 longdesc 属性中包含 html 链接 我已经将 Prettyphoto 更改为使用 longdesc 而不是图像标题 但我需要在这些描述中包含 html 链接 我知道字符代码是可能的 我只是不记得那些是什么 Than
  • 如何使用 CMake 生成 Windows DLL 版本信息?

    这非常类似于 如何使用 CMake 生成 Windows DLL 版本控制信息 但我想我可能会再问一次 因为从那以后事情可能发生了变化 使用以下 CMakeLists txt 文件 https github com malaterre GD
  • AsyncTask 取消不起作用

    我正在学习如何取消 asyncTask 因此下面的代码没有用处 我尝试调用 asyncTask 并执行它 然后取消它并执行它 MyAsyncTask asyncTask new MyAsyncTask Log i cancel cancel
  • 使用 python 查找 HTML 代码中的特定注释

    我在 python 中找不到具体的注释 例如 我的主要原因是找到 2 个特定评论中的所有链接 像解析器之类的东西 我尝试过这个Beautifulsoup import urllib over urlopen www gamespot com
  • Java中如何比较int数组? [复制]

    这个问题在这里已经有答案了 当我尝试比较两个 int 数组时 即使它们完全相同 里面的代码if one two 仍然没有被执行 为什么是这样 Object one 1 2 3 4 5 6 7 8 9 Object two 1 2 3 4 5
  • 循环遍历集合中的 jQuery 对象,而不为每次迭代初始化新的 jQuery 对象

    我发现自己一直在这样做 myElements each function index currentHtmltmlElement var currentJqueryElement currentHtmltmlElement Working
  • 在 Lisp 中打印 defstruct

    我在 Lisp 中定义了一个非常简单的数据结构 Data structure for a person defstruct person name nil age 0 siblings nil type list Siblings is a
  • 寻找特定顶点最短路径的好算法

    我正在解决下面描述的问题 并且想不出比尝试每个组的每个顶点的每个排列更好的算法 我得到了一张顶点图 以及一组特定顶点组的列表 目标是找到从特定起始顶点到特定结束顶点的最短路径 并且该路径必须从每个顶点至少经过一个顶点指定的顶点组 图中还存在