Algorithm 图中的约束最短路径

Algorithm 图中的约束最短路径,algorithm,Algorithm,以下是我在一个在线法官网站上发现的问题: 我有一个无向图(带循环)。图中有k类不同的顶点。您可以将第1类顶点视为绿色,第2类顶点视为红色,依此类推。还有一类特殊的顶点颜色为白色(稍后将详细介绍) 现在,用户将指定一个源顶点、一个目标顶点和一系列不同的顶点类(非白色),例如 我们得到了源顶点10、目标顶点40和一个序列:红色->蓝色->黑色 我们必须找到最短路径,这样路径从顶点10开始,接触1个红色顶点,然后是1个蓝色和1个黑色顶点,然后到达顶点40。但是,路径可以根据需要具有任意多个白色顶点。它

以下是我在一个在线法官网站上发现的问题:

我有一个无向图(带循环)。图中有k类不同的顶点。您可以将第1类顶点视为绿色,第2类顶点视为红色,依此类推。还有一类特殊的顶点颜色为白色(稍后将详细介绍)

现在,用户将指定一个源顶点、一个目标顶点和一系列不同的顶点类(非白色),例如

我们得到了源顶点10、目标顶点40和一个序列:红色->蓝色->黑色

我们必须找到最短路径,这样路径从顶点10开始,接触1个红色顶点,然后是1个蓝色和1个黑色顶点,然后到达顶点40。但是,路径可以根据需要具有任意多个白色顶点。它还可以遍历白色顶点两次

因此,解决方案可以是:10->20(白色)->35(红色)->21(白色)->22(白色)->30(蓝色)->34(黑色)->40

不正确:

10->20(白色)->30(蓝色)->21(白色)->22(白色)->35(红色)->34(黑色)->40(在红色之前变为蓝色)


10->20(白色)->35(红色)->56(红色)->21(白色)->22(白色)->30(蓝色)->34(黑色)->40(穿过红色两次)

您可以使用dijkstra算法,附加标志显示顶点路径是否满足条件。

您可以使用dijkstra算法,附加标志显示顶点路径是否满足条件。

假设A1(稍后提升):序列S中不存在两次颜色

然后我们可以使用以下算法B1

  • 在有向图G'中按以下方式变换图G:
    • G'具有与G相同的节点
    • 如果v是白色节点且(v,u)存在于G中,则在G'中插入(v,u)和(u,v)
    • 如果(v,u)存在于G中且(颜色(v),颜色(u))存在于S中,则在G'中插入(v,u)
    • 忽略G的所有其他边(包括循环)
  • 为所有边指定相同的权重
  • 在G'上执行最短路径算法,例如Bellman Ford
  • 现在我们放松A1:假设A2:S中只有一种颜色存在多次

    算法B2

  • wl.o.g.,c0是S中多次存在的颜色,更精确地说是n次
  • 将S划分为子序列S1、S2、。。。其中S1=(c1,c2,…,c0),S2=(c3,…,c0)
  • 生成图G1,G2。。。通过关于步骤1的转换G。每个S_i的B1值
  • 通过连接G1,G2,…,形成一个图G',。。。Gn
    • 将G1中颜色为c0的每个节点与颜色为c3的每个节点以及G2中的任何白色节点连接起来
    • 对G2和G3等进行同样的操作
  • 应用最短路径算法,源在G1,目标在Gn
  • 扩展到序列中的多个重复颜色:


    将序列拆分为没有重复颜色的序列,并以类似方式应用B2。

    假设A1(稍后取消):序列S中不存在两次颜色

    然后我们可以使用以下算法B1

  • 在有向图G'中按以下方式变换图G:
    • G'具有与G相同的节点
    • 如果v是白色节点且(v,u)存在于G中,则在G'中插入(v,u)和(u,v)
    • 如果(v,u)存在于G中且(颜色(v),颜色(u))存在于S中,则在G'中插入(v,u)
    • 忽略G的所有其他边(包括循环)
  • 为所有边指定相同的权重
  • 在G'上执行最短路径算法,例如Bellman Ford
  • 现在我们放松A1:假设A2:S中只有一种颜色存在多次

    算法B2

  • wl.o.g.,c0是S中多次存在的颜色,更精确地说是n次
  • 将S划分为子序列S1、S2、。。。其中S1=(c1,c2,…,c0),S2=(c3,…,c0)
  • 生成图G1,G2。。。通过关于步骤1的转换G。每个S_i的B1值
  • 通过连接G1,G2,…,形成一个图G',。。。Gn
    • 将G1中颜色为c0的每个节点与颜色为c3的每个节点以及G2中的任何白色节点连接起来
    • 对G2和G3等进行同样的操作
  • 应用最短路径算法,源在G1,目标在Gn
  • 扩展到序列中的多个重复颜色:

    将序列拆分为无重复颜色的序列,并以类似方式应用B2。

    我可以建议一种基于简单图形修改(完成bfs修改)的O(n*(n+m))解决方案。让我一步一步地描述一下

    图形修改。

  • 为了避免任何麻烦,颜色源和白色顶点在一些独特的颜色
  • 使图形加权。原始存在边的权重为1
  • 对于每对彩色顶点u,v添加一条边(u,v),其权重等于从u到v的最短白色路径。白色路径是只经过白色顶点的路径。如果没有这样的白色路径,请不要添加边
  • 删除所有白色顶点及其相邻边 第二点可以通过从每个仅经过白色顶点的顶点运行bfs来实现。这将在O(n*(n+m))中运行

    等效性。

    现在我们有一个没有白色顶点的加权彩色图,很容易看出问题在修改后保持不变-我们仍然需要找到从源顶点到目标顶点的最短路径(现在是边权重和)

    搜索算法。

    要解决此图上的问题,请运行bfs的变体,其中的层对应于提供的路径的颜色。这意味着,如果给定路径“红色->蓝色->黑色”,则bfs将首先移动到与源相邻的所有红色顶点,然后移动到与红色标记相邻的所有蓝色顶点,然后移动到与蓝色标记相邻的所有黑色顶点,最后移动