我可以使用什么算法来查找图中指定节点类型之间的最短路径?

时间:2009-07-17 12:35:44

标签: algorithm math graph graph-theory shortest-path

这是问题所在:

我有n个点(p1,p2,p3,.. pn),每个点都可以以确定的成本x连接到任何其他点。

每个点都属于一组点类型之一(例如“A”“B”“C”“D”......)。

方法的输入是我想要遵循的路径,例如“A-B-C-A-D-B”。

输出是连接输入类型I的点的最短路径,例如“p1-p4-p32-p83-p43-p12”,其中p1是A型,p4是B型,p32 C型,p83型,A型,p43型,D型,p12型,B型。

“简单”解决方案包括计算所有可能的路径,但计算成本非常高!

有人能找到更好的算法吗?

正如我在标题中所说,我不知道它是否存在!

更新

阻止我使用Dijkstra和其他类似算法的关键点是我必须根据类型链接点。

作为输入我有一系列类型,我必须按顺序链接。

这是Kent Fredric的图片(非常感谢),描述了最初的情况(红色允许的链接)!

alt text

一个现实生活中的例子:

一个男人想早上去教堂,去餐馆,下午去博物馆。

地图上有6个教堂,30个餐厅和4个博物馆。

他希望教堂休息博物馆的距离是最小的。

7 个答案:

答案 0 :(得分:7)

您可以使用Floyd-Warshall算法。这是WikiPedia给出的伪代码:

/* Assume a function edgeCost(i,j) which returns the cost of the edge from i to 
   (infinity if there is none).
   Also assume that n is the number of vertices and edgeCost(i,i)=0
*/

int path[][];

/* A 2-dimensional matrix. At each step in the algorithm, path[i][j] is the shortest path
   from i to j using intermediate vertices (1..k-1).  Each path[i][j] is initialized to
   edgeCost(i,j) or infinity if there is no edge between i and j.
*/

procedure FloydWarshall ()
    for k: = 1 to n
        for each (i,j) in {1,..,n}2
            path[i][j] = min ( path[i][j], path[i][k]+path[k][j] );

我必须编写关于同一问题的算法课程的程序。这个算法就像一个魅力!古德勒克。

答案 1 :(得分:4)

有许多算法比计算所有可能的路径都要好。 Breadth-first search是我想到的算法族的基本起点,Best-first search是合适的,因为您定义了顶点成本,如果您可以获得有关您的问题空间的更多信息,您可能能够使用A*Dijkstra's algorithm。 (在每种情况下,从允许的起始节点集中查找路径。)

重新编辑:您的路径约束(您需要满足的节点类型数组)不会阻止您使用这些算法;恰恰相反,它可以帮助他们更好地工作。您只需要以允许合并路径约束的方式实现它们,将搜索中每个步骤可用的顶点限制为在给定约束条件下有效的顶点。

答案 2 :(得分:4)

正如Jan所提到的,你只需要一个普通的无聊最短路径算法(如Dijkstra或Floyd's算法);但是,您需要转换输入图形,以便输出路径将遵循路径约束。

给出路​​径约束:A - B - A

创建一个新图G,并将A中的所有顶点插入到G中,并使用新标签(如a_01)。然后将B中的所有顶点插入G并将A顶点与B顶点连接(边缘应指向新插入的节点)复制成本原始图。然后,使用A(和任何其他路径组件)将新插入的顶点连接到B中的顶点,重复此步骤。因此,您创建一个图形,其中只有存在的路径满足路径约束。然后,您可以使用常规的最短路径算法。

关键的见解是,当您重新访问一个类时,您实际上正在访问一组不同的节点,并且您只需要连接相邻节点类的边。

答案 3 :(得分:2)

在您的问题的修订版中,您似乎要求每个字母一个节点 - 在这种情况下,它是一个简单的动态编程解决方案:计算长度为1的所有最短路径,这些路径满足序列的开始,每对之间节点然后为所有节点对提供k所有这些路径,为k + 1构造是微不足道的。

答案 4 :(得分:2)

这是带有动态编程解决方案的伪代码:

n - length of desired path
m - number of vertices
types[n] // desired type of ith node
vertice_types[m]
d[n][m] // our DP tab initially filled with infinities

d[0][0..m] = 0
for length from 1 to n 
  for b from 0 to m
    if types[length] == vertice_types[b]
      for a from 0 to m
        if types[length-1] == vertice_types[a]
          d[length][b] = min(d[length][b], d[length-1][a] + cost(a,b))

您的最低成本路径是min(d [n] [0..m])

你可以将d表的大小减少到2行,但它会使解决方案混淆

答案 5 :(得分:1)

据我了解你的问题,你需要有向图中的最短路径。 http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm应该给你一个想法。

问候,Jan

答案 6 :(得分:1)

  1. 计算每个等价块中的所有最短路径对。
  2. 现在构建一个没有类间边缘的图形,但它的类之间的边缘与该类中的最短路径匹配,从而导致另一个类的特定节点。
  3. 希望这很清楚。

    这种解决方案不是特别有效,但显然是多项式的。