You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改Floyd-Warshall算法求解指定中间顶点数的Top-K最短路径?

修改Floyd-Warshall实现任意顶点对的Top-K最短路径(支持带环路径)

要实现你需求的「任意顶点对Top-K最短路径(允许路径含重复顶点),且自身到自身路径排除0代价空路径」,我们需要对Floyd-Warshall的状态定义和松弛逻辑做针对性修改,核心是从单条最短路径扩展为维护前K条最小代价路径的集合。

核心修改思路

原Floyd-Warshall用dist[i][j]存储i到j的单条最短路径代价,我们把它替换成二维列表数组topk[i][j]——每个列表专门存从i到j的前K条最短路径的代价,始终保持升序排列。同时,针对你提到的「v1到v1的路径不能是0」的要求,初始化时不给topk[i][i]设置0值,而是通过后续的环路径松弛生成有效代价。

具体实现步骤

1. 初始化阶段

首先准备图的邻接矩阵w,w[i][j]代表i到j的直接边代价(没有直接边就设为无穷大,比如float('inf'))。然后初始化topk数组:

  • 对i≠j的顶点对:如果w[i][j]不是无穷大,topk[i][j]初始化为[w[i][j]](直接边作为第一条候选路径);
  • 对i=j的顶点对:topk[i][j]初始化为空列表(跳过0代价的空路径);
  • 其余无直接边的顶点对,topk初始为空。

2. 扩展松弛逻辑

原Floyd-Warshall的松弛是取最小值,现在我们要组合所有可能的路径代价,筛选出前K个最小的:
按标准Floyd-Warshall的三层循环顺序(遍历所有中间顶点k,再遍历所有i、j),对每个(i,j):

  • 生成候选代价:把topk[i][k]里的每个代价,和topk[k][j]里的每个代价相加,得到所有i→...→k→...→j路径的总代价;
  • 合并筛选:把候选代价和topk[i][j]原有的代价合并,去重后按升序排序,只保留前K个最小的代价更新topk[i][j]。

3. 适配自身到自身的非空路径

因为初始化时topk[i][i]是空的,后续通过松弛过程,比如i→k→i、i→k→l→i这类带环的路径代价会被逐步加入。你需要的「k=3个中间顶点(即4条边)的v1到v1路径代价6」,会在多次松弛后被筛选进topk[v1][v1]的前K项中。

结合你的例子验证

假设你的图权重如下:

  • w(v1,v3)=4,w(v3,v2)=1,w(v2,v3)=1,w(v3,v5)=2,w(v3,v1)=0(用于生成v1→v3→v2→v3→v1的6代价路径)
  • 其他无直接边的顶点对权重设为无穷大

关键松弛步骤

  1. 当中间顶点k=v3时:
    • 生成v1→v3→v1,代价4+0=4,加入topk[v1][v1];
    • 生成v3→v2→v3,代价1+1=2,加入topk[v3][v3];
  2. 当中间顶点k=v2时:
    • 生成v1→v3→v2→v3,代价4+1+1=6,加入topk[v1][v3];
    • 生成v1→v3→v2→v3→v1,代价4+1+1+0=6,加入topk[v1][v1];
  3. 当中间顶点k=v3再次遍历:
    • 生成v1→v3→v2→v3→v5,代价4+1+1+2=8,加入topk[v1][v5];

最终结果

  • 当K=3时,topk[v1][v1]的前3条路径代价包含6(假设前两条是4和6,第三条是更高的代价);
  • topk[v1][v5]的路径代价中,8会被纳入前K项,符合你给出的例子要求。

注意点

  • 带环路径允许:如果需要限制路径为无重复顶点的简单路径,得额外记录路径中的顶点集合,复杂度会大幅上升——你的例子里包含重复的v3,所以我们采用允许带环的逻辑;
  • 去重与排序:每次合并后必须去重排序,否则会出现重复代价,且无法保证前K个是最小的;
  • 无穷大值:初始化时用足够大的数值表示无直接边,避免无效的路径组合。

内容的提问来源于stack exchange,提问作者Subhamm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 20:50:08