给定一幅加权有向图,以及一个起点 s 和一个终点 t ,找到 s 到 t 的最短路径。 如果不包含负权重,可以在 Dijkstra 算法中,从优先队列取出目标顶点 t 之后终止搜索,而 distTo[t] 则为最短路径值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
publicDijkstraSP(EdgeWeightedDigraph G, int s){ ...
// relax vertices in order of distance from s pq = new IndexMinPQ<Double>(G.V()); pq.insert(s, distTo[s]); while (!pq.isEmpty()) { int v = pq.delMin(); // 如果 v 为终点,则跳出循环,计算结束 if (v == endVertex) break; for (DirectedEdge e : G.adj(v)) relax(e); } ... }
加权有向无环图的最长路径
给定一幅无环加权有向图和起点 s,是否存在一条 s 到给定顶点 v 的路径?找出最长(总权重最大)的路径。
publicAcyclicLP(EdgeWeightedDigraph G, int s){ distTo = newdouble[G.V()]; edgeTo = new DirectedEdge[G.V()];
validateVertex(s);
// 初始化为负无穷 for (int v = 0; v < G.V(); v++) distTo[v] = Double.NEGATIVE_INFINITY; distTo[s] = 0.0;
// relax vertices in topological order Topological topological = new Topological(G); if (!topological.hasOrder()) thrownew IllegalArgumentException("Digraph is not acyclic."); for (int v : topological.order()) { for (DirectedEdge e : G.adj(v)) relax(e); } }
// relax edge e, but update if you find a *longer* path privatevoidrelax(DirectedEdge e){ int v = e.from(), w = e.to(); // 放松时,改为小于 if (distTo[w] < distTo[v] + e.weight()) { distTo[w] = distTo[v] + e.weight(); edgeTo[w] = e; } }
取每条边权重的自然对数并取反,这样套汇问题中的权重之积的计算转换为新图中的所有边权重之和的计算。任意权重之积 w1*w2*...wk 即对应 -lnw1-lnw2...-lnwk 之和。转换后边的权重可能为正也可能为负,一条从 v 到 w 的路径表示将货币 v 兑换为货币 w,任意负权重环都是一次套汇机会。