假设我有一个加权图,边缘和顶点都有权重。如何找到从某个节点到某个节点的“最便宜”路径?我的复杂性应该是O(n 2 (n + m))。
答案 0 :(得分:5)
解决此问题的一种方法是将图形转换为新图形,其中只有边缘被加权,而不是顶点。为此,您可以将每个节点拆分为两个节点,如下所示。对于任何节点v,请创建两个新节点v1和v2。之前进入节点v的所有边缘现在都进入节点v1,离开节点v的所有边缘现在都离开v2。然后,在v1和v2之间放置一个边,其成本是节点v1的成本。
在这个新图中,从一个节点到另一个节点的路径的成本对应于原始图中原始路径的成本,因为仍然支付了所有边权重,并且现在使用新插入的方式支付所有节点权重边缘。
构造此图应该在时间O(m + n)中可行,因为您需要将每个边精确地更改一次,并且每个节点只需更改一次。从那里,你可以使用正常的Dijkstra算法来解决时间O(m + n log n)的问题,给出总体复杂度为O(m + n log n)。如果存在负权重,则可以使用Bellman-Ford算法,总复杂度为O(mn)。
希望这有帮助!
答案 1 :(得分:0)
修改后的Djkstra应该有效
1 function Dijkstra(Graph, source):
2 for each vertex v in Graph: // Initializations
3 dist[v] := infinity ; // Unknown distance function from
4 // source to v
5 // Previous node in optimal path
6 end for // from source
7
8 dist[source] := source.cost ; // Distance from source to source
9 Q := the set of all nodes in Graph ; // All nodes in the graph are
10 // unoptimized - thus are in Q
11 while Q is not empty: // The main loop
12 u := vertex in Q with smallest distance in dist[] ; // Start node in first case
13 remove u from Q ;
14 if dist[u] = infinity:
15 break ; // all remaining vertices are
16 end if // inaccessible from source
17
18 for each neighbor v of u: // where v has not yet been
19 // removed from Q.
20 alt := dist[u] + dist_between(u, v)+v.cost ;
21 if alt < dist[v]: // Relax (u,v,a)
22 dist[v] := alt ;
23
24 decrease-key v in Q; // Reorder v in the Queue
25 end if
26 end for
27 end while
28 return dist;
答案 2 :(得分:0)
我认为可以在图G'中转换图G,我们只有边加权。转换算法非常简单,因为当我们从A - >移动时,我们有边和节点加权。 B,我们知道从A移动到B的总重量是边缘的重量(A - > B)加上B本身的重量,所以让A - > B边权重和这两个权重和B的权重为零。我们可以找到从任何节点到任何节点到O(mlogn)的最短路径(n - 节点数,m - 边数)