我需要一段代码,找到权重最大的节点之间的最短路径。例如,从A到D的最快路线,但权重最大:
- B- --E
/ \ /
A D
\ / \
C - -F
所以现在最短的是ABD或ACD。一旦加权,代码应该选择两个中最长的路径(反直觉,是吗?)。
我试图修改Dijkstra算法的算法,但最终我最终遍历了整个图表。谁会知道怎么做? 即使只是一个算法,所以我可以自己编码也会有很大的帮助。
答案 0 :(得分:2)
s
)运行BFS以查找
从s
到目标t
的最短路径的长度,设为d
。同时标记d(s,v)
- 从s
到任何节点v
的距离。G'=(V',E')
的子G
,以便:v
位于V'
仅当它与来源(s
)的距离最多为d
- d(s,v) <= d
时。仅当e=(u,v)
和E'
都在u
时,v
才会出现在V'
。G*=(V*,E*)
和V'=V*
中有(u,v)
,那么E*
和E'
边缘d(s,u) < d(s,v)
位于w*(u,v) = -w(u,v)
G*
,并使用w*
在G
上运行Bellman Ford。s
到t
的{{1}}中最重的最短路径的重量为-d(t)
,而BF找到的路径是匹配的路径。算法的时间复杂度为O(VE)
,因为Bellman-Ford是瓶颈。
正确性证明
声明1:从s
到t
的最短路径不包含任何周期。
通过消除循环我们得到一条较短的路径,证明很简单。
声明2:从s
到t
的所有最短路径都位于G'
证明:由于从s
到t
的所有最短路径长度为d
,因此我们仅删除距s
的距离比d
长的节点},我们只删除最短路径不需要的节点。
权利要求3:从s
到t
的所有最短路径都在G*
中。
证明:假设我们在最短路径中删除了一些边(u,v)
,并让该路径为s->...->x->u->v->y->...->t
。请注意,路径v->y->..->t
的长度为d-d(s,u)-1
(假设d(s,u)
最小)
但请注意,E*
的构造,d(s,v) <= d(s,u)
(否则(u,v)
将不会被移除)。因此,路径s->...->v->y->...->t
的距离为s
:d(s,v) + d-d(s,u)-1 <= d(s,u) + d - d(s,u) -1 <= d-1
- 与d
的最小值相矛盾。
权利要求4:G*
中没有循环。
证明:假设G*
:v1->v2->vk->v1
中有一个周期。根据G'的定义,所有节点都可以从s
到达。在不失一般性的情况下,让我们假设d(s,v1)
对于所有其他d(s,vi)
都是最小的(否则旋转索引以匹配此假设)。但是存在路径v1-> v2-> ...->&gt; vk-> v1和d(s,v1)=d(s,v1)
。这意味着至少对于此路径中的一个边(vi,vi+1)
d(vi) >= d(vi+1)
- 这与E*
的构造相矛盾,并且G *中不存在该循环。
权利要求5:算法是正确的。
从Bellman-Ford的正确性开始,由于G*
不包含负循环(根本没有循环),BF将根据w*
中的G*
找到权重最小的路径。根据{{1}}的{{1}}构造,此路径是最大权重的路径。
由于w
中的所有最短路径也存在于w*
中(并且只有它们),因此该路径也是G
中具有最大权重的最短路径。
<强> QED 强>
答案 1 :(得分:-1)
如果你调整你的体重,你可以使用Dijkstra。
如果您的最佳路径必须是访问最少节点的路径,则可以使用高惩罚 p 来遍历每条边并减去实际权重:
w '= p - w
必须选择高于最高权重 w max 的惩罚,以防止 w '的负值,Dijsktra不会工作。它也必须足够高,以便选择真正最短的路径。 n 节点图的 p 的良好估计可能是:
p ≈ n · w max
(编辑:我的原始答案建议使用每条边的倒数权重 w '= 1 / w 而不是实际权重< em> w 作为替代方案。这不一定会给你最短的路径,但是在穿越少数边缘时权重很高的路径。这个解决方案在很多情况下都不起作用。但是,它完全独立于惩罚方法,不使用倒数值。)