基础

带权图与无权图详解

图本身从不改变,改变的是叠加在它上面的函数。本指南沿着这个函数,依次讲解“最短路径”的两种含义、权重沿路径组合的三种方式、每种权重迫使你使用的算法,以及 Dijkstra 恰好在哪一点不再正确。

阅读时间 18 分钟 更新时间:2026 年 9 月 入门级
Mohammed Islam Hadjoudj
Mohammed Islam Hadjoudj
Expert Operations Research Engineer

1. 权重是函数,不是图的一部分

图是一对集合 G = (V, E),这个定义中根本没有提到数字。距离、成本、容量和时长都来自外部,是附加在同一边集上的一个独立函数:

G = (V, E)                    图:哪些顶点对相连
w: E → ℝ                    权重函数:每条连接的代价

标准教材有意强调这种分离。Bondy 和 Murty 把带权图定义为一个图加上为每条边指定的一个实数,然后把子图的权重定义为其各边权重之和,而这正是最短路径或最小生成树所要最小化的量。Diestel 也以同样的方式处理权重,把它们视为叠加在一个不变的组合对象之上的额外数据。

w 放在图之外并非吹毛求疵,它带来三点好处:

于是,无权图就是没有提供此类函数的图,下一节会说明,这等同于提供了最乏味的那个函数。

2. 无权意味着每个权重都是 1

要同时理解这两种情况,最清晰的方式是不再把“无权”看作没有权重,而是把它看作一种特定的权重选择:

无权图就是满足以下条件的带权图: w(e) = 1 对每条边成立。于是路径的权重就是它的边数,所以“最短路径”意味着“边数最少”。

一切都源于这一次替换。广度优先搜索找到边数最少的路径,它恰好就是 Dijkstra 算法在所有权重都为 1 时退化成的样子:优先队列从不需要重新排序,因为距离本来就按非递减的整数顺序出队,一个普通的 FIFO 队列就能在 O(n + m)内完成同样的工作。Edward Moore 1959 年的论文“The shortest path through a maze”提出并解决的正是这个单位权重问题,这个算法通常也追溯到这篇论文。

这种替换反过来也成立,而权重的代价正体现在这里。给同一个图赋予任意正权重,FIFO 队列就不再适用,因为边更多的路径现在可能更便宜。你需要优先队列,运行时间从 O(n + m) 变为使用二叉堆时的 O(m log n) ,或使用 Fredman 和 Tarjan(1987)的斐波那契堆时的 O(m + n log n)

3. 最短路径并非最短路径

这张图展示了全部区别。同样的五个顶点、同样的五条边、同样的问题,根据有没有数字,会得到两个不同的答案。

同一个五顶点图的两个副本,边为 A 到 B、B 到 C、C 到 D、A 到 D 和 D 到 E。左侧的图无权,广度优先搜索返回只有一条边的路径 A 到 D。右侧同一个图带有权重 1、1、1、7 和 2,Dijkstra 返回三条边的路径 A 到 B 到 C 到 D,总成本为 3,而单条边 A 到 D 的成本为 7。下方的面板对比两个答案:边数最少是一条成本为 7 的边,权重最小是三条成本为 3 的边。
边数最少与权重最小是不同的目标。从 A 到 D 的单条边在无权图中是最短路径,在带权图中却是最差的一条。

完整写出来,这个图是

V = {A, B, C, D, E}
E = { {A,B}, {B,C}, {C,D}, {A,D}, {D,E} }
w =    1       1       1       7       2

两个问题的答案如下:

问题算法找到的路径边数总权重
从 A 到 D 边数最少BFSA → D17
从 A 到 D 总权重最小DijkstraA → B → C → D33
从 A 到 E 边数最少BFSA → D → E29
从 A 到 E 总权重最小DijkstraA → B → C → D → E45

注意,带权的答案在两行中都使用了更多的边。这是常态,而不是刻意构造的情况:绕行高速公路经过的路口更多,花费的分钟却更少。在带权图上运行 BFS 得到的不是近似答案,而是另一个问题的答案,两者之间的差距没有上界。把 {A, D} 的权重提高到一百万,BFS 仍然会返回它。

4. 权重的含义:三种组合方式

“带权图”只是一个容器,而不是一种含义。在选择算法之前,你必须先回答一个问题:路径上的权重如何组合成你关心的那个值?常见的答案有三种,它们导向三个不同的问题。

三个面板展示同一条三边路径,权重为 4、2 和 6。在加性面板中,路径值是总和 12,标注为成本、距离或时间,用 Dijkstra 求解。在瓶颈面板中,路径值是最小值 2,标注为容量或带宽,用最宽路径或最大生成树方法求解。在乘性面板中,权重是概率 0.9、0.8 和 0.5,其乘积为 0.36,并注明取负对数可以把乘积变成求和,从而再次适用 Dijkstra。
同一条路径上的同样三个数字给出三种不同的路径值。你要哪一种,在写下任何代码之前就决定了算法。
组合规则权重的含义路径值问题与方法
加性距离、成本、时间、跳数各边之和最短路径:BFS、Dijkstra、Bellman-Ford
瓶颈容量、带宽、最薄弱环节的可靠性路径上的最小边最宽路径,也称 maximin 或 minimax 路径;用改进的 Dijkstra 或借助最大生成树求解
乘性链路可用的概率、传输速率各边之积最可能路径:代入 -log w 后即变为加性

乘性技巧值得详细说明,因为从路由到自然语言解码,它无处不在。沿路径最大化概率之积,等同于最小化它们负对数之和,因为 -log 是单调递减的,并把乘积变成求和。由于每个概率至多为 1,每个 -log w 都是非负的,所以 Dijkstra 可以直接使用,不需要任何特殊算法。

还有一个区别造成的建模错误比以上所有问题都多,而且它与算术毫无关系:

数值越大,是表示越近还是越远?在距离图中,权重大是坏事,你要最小化。在相似度图中,权重大是好事,你要最大化。两者正好相反,而文件格式不会告诉你手里的是哪一种。

相关性网络、共同购买图和嵌入相似度图都是按相似度加权的,因此把它们交给最短路径程序,算出的是经过最不相似链接的路径。如果你需要从相似度得到距离,就要有意识地转换: d = 1 - s 适用于取值在 [0, 1] 内的相似度,或者 d = 1/s,或者 d = -log s。每种选择都会改变路径的排序,所以这是一个建模决策,而不是走形式。

5. 权重替你选择算法

一旦组合规则是加性的,仅凭权重函数的形态就能决定算法。这正是带权与无权之区别的实际核心。

权重使用时间原因
全部相等(无权)BFSO(n + m)FIFO 队列本来就会给出非递减的距离
只有 0 和 1用双端队列的 0-1 BFSO(n + m)权重为 0 的边插到队首,权重为 1 的边插到队尾,双端队列始终有序
小整数,上界为 CDial 桶队列O(m + nC)当距离的取值范围较小时,用桶代替堆
任意非负DijkstraO(m log n),使用斐波那契堆时为 O(m + n log n)贪心的确定步骤要求距离非递减
任意实数,无负环Bellman-FordO(nm)把每条边松弛 n-1 次,不需要任何顺序假设
有负权边,全源Johnson 算法O(nm + n² log n)先用 Bellman-Ford 重新赋权一次,使所有权重非负,再从每个顶点运行 Dijkstra

表中有两项值得说明。 0-1 BFS 基于一个巧妙的观察:如果权重只有 0 或 1,就根本不需要堆,双端队列可以免费保持边界有序,从而恢复线性时间。 Johnson 算法出自他 1977 年发表在 Journal of the ACM上的论文,是在带负权边的图上保持 Dijkstra 速度的标准方法:它加入一个势函数,使每条重新赋权的边都非负,同时保持哪些路径最短不变。

在无权情形的边界上还有一个引人注目的结果。Thorup 在 1999 年证明,对于带正整数权重的无向图,单源最短路径可以在线性时间内求出,与 BFS 相当,其方法是利用整数权重的结构,而不是比较距离。对于比较-加法模型中的任意实数权重,目前还没有类似的线性时间结果,这提醒我们,“带权”不是一个问题,而是一族问题,其难度取决于权重的形态。

6. 负权重,以及 Dijkstra 为何失效

Dijkstra 1959 年的短文假设权重非负,而这个假设是承重的,并非装饰。算法是贪心的:一旦把某个顶点从队列中取出,就宣布它已确定,并且再也不回头检查。只有当之后发现的路径不可能更便宜时,这才是正确的,而非负性恰好保证了这一点,因为延长路径只会增加成本。

只要引入一条负权边,这个保证就会失效。下面是一个小到可以手工追踪的反例,而且没有并列情况,出队顺序是确定的:

一个四顶点有向图。S 到 A 的成本为 1,A 到 B 为 1,S 到 C 为 3,C 到 B 为负 5。Dijkstra 按 S 为 0、A 为 1、B 为 2、C 为 3 的顺序确定顶点,因此在查看从 C 出发的弧之前就把 B 定为 2。经由 S 到 C 到 B 的路线,到 B 的真实最短距离是负 2。一个面板对比贪心答案 2 与正确答案负 2。
Dijkstra 在 C 仍在队列中时就把 B 确定为 2。从 C 出发的弧权重为 -5,因此真实距离是 -2,但 B 已经关闭,答案再也不会被修正。

追踪一下:队列取出距离为 0 的 S,把 A 松弛为 1,C 松弛为 3。取出距离为 1 的 A,把 B 松弛为 2。取出距离为 2 的 B,并标记为已确定。直到这时,它才取出距离为 3 的 C,发现权重为 -5 的弧 C → B ,它本会使 B 的距离变为 -2。由于 B 已经确定,这一改进被丢弃,算法报告 2 而不是 -2。

有两点澄清比反例本身更重要:

负权重并不罕见。套利链把货币兑换定价为乘积,乘积再变成负对数之和,而有利可图的环在模型中就表现为负环。这是负权检测的标准教科书应用,也正因如此,Bellman-Ford 多出的那个 n倍因子是值得的。

7. 只有带权时才存在的问题

有些问题在无权时并不是更难,而是空洞。最明显的例子是最小生成树。

在无权连通图中,每棵生成树恰有 n - 1 条边,所以每棵生成树都是最小的,任何一次遍历都能解决问题:BFS 或 DFS 树本身就是答案。加上权重,这个问题才变得真实,因为生成树的总成本各不相同,而找出最便宜的那棵,正是 Borůvka 在 1926 年、Kruskal 在 1956 年和 Prim 在 1957 年各自解决的问题。

在贯穿示例中,最小生成树选取 {A,B}{B,C}{C,D}{D,E} ,总权重为 5,并舍弃了昂贵的 {A,D} (权重 7)。如果不带权,这个图的四棵生成树都一样好。

问题无权带权
最短路径边数最少,BFS,O(n + m)总权重最小,Dijkstra 或 Bellman-Ford
最小生成树平凡:所有生成树都一样真正的问题: KruskalPrim、Borůvka
最大流单位容量,一种特殊情形容量就是权重;这是整个领域
匹配最大基数匹配最大权匹配,另一种算法
最宽路径没有意义瓶颈目标,见第 4 节
聚类与社区发现基于边是否存在基于边的强度,这会改变发现的社区
中心性路径数与邻居数带权变体;度变成强度,见第 9 节

最大流是生成树情形的镜像。容量就是权重函数,所以无权流网络意味着单位容量,而在这种特殊情形下,根据 Menger 定理,最大流归结为统计边不相交路径的数目。Ahuja、Magnanti 和 Orlin 的 Network Flows 是一般带权处理的标准参考书,其中每条弧通常同时带有容量和成本,也就是一个图上有两个权重函数。

8. 存储权重,以及零与无穷大的陷阱

两种标准表示都可以用显而易见的方式扩展,而且各有一种值得点明的失效模式。

邻接矩阵。元素 (u, v) 不再是 0 和 1,而是存放这条边的权重。陷阱立刻出现:没有边的格子里放什么?0 是诱人的默认值,但它是错的,因为 0 是完全合法的权重,两种情况会变得无法区分。在最短路径场景下,用 表示“没有边”,因为它是最小化运算的单位元,并在对角线上保留 0。在无权矩阵中,同一个格子用值 0 表示“没有边”,这正是从无权代码移植到带权代码时在这里出错的原因。

无权       A[u][v] = 连通则为 1,否则为 0
带权       A[u][v] = 连通则为 w(u,v),否则为 ∞      (对角线为 0)

哨兵 bug   用 A[u][v] = 0 表示“没有边”会让权重为 0 的边
           不可见,所有距离都塌缩为 0

邻接表。每个条目从单个顶点变为一个对,因此表中存放的是 (邻居, 权重)。其他一切不变,这就是邻接表成为带权问题默认选择的原因:每条存储的边只多占一个数字的内存,遍历循环完全相同。

还有第三种格式对带权图特别重要。边列表由三元组 (u, v, w) 构成,它是 Kruskal 算法的天然输入,该算法按权重对整个列表排序;它也是 Bellman-Ford 的天然输入,后者依次松弛每条边。两者都不需要查找邻居,所以都完全不需要邻接结构。

9. 度变成强度

权重不仅改变算法,也改变描述性统计量。顶点的度在带权情形下的对应物是它的强度,即其关联边的权重之和:

deg(v)  =  关联边的数量                     无权计数
s(v)    =  ∑ w(e),对 v 的所有关联边求和     带权总和

Barrat、Barthélemy、Pastor-Satorras 和 Vespignani 在 2004 年关于带权网络的 PNAS 论文中引入了这个术语,它之所以重要,是因为这两个量对顶点的排序可能完全不同。一个拥有许多小型支线航线的机场,度高而强度低;一个拥有四条巨大远程航线的枢纽,度低而强度高。问“哪个机场最重要”,取决于你计算的是哪个量,答案会不同,而且两者都没有错。

同样的分歧贯穿网络分析的其他部分。Newman 2004 年的论文“Analysis of weighted networks”展示了聚类系数、模块度和中心性如何各自获得带权版本,以及同一指标的带权与无权版本在同一数据上经常不一致。当你报告一个网络统计量时,说明它是否使用了权重不是脚注,而是定义的一部分。

10. 何时添加权重,何时不要

权重不是免费的。它们让你失去线性时间算法,在每一步都增加一个建模决策,并引入无权图根本不存在的尺度敏感性。只有当答案真正取决于数值大小时,才使用它们:

带权数据有两点特别的注意事项。第一,尺度很重要:把所有权重乘以一个常数,最短路径和最小生成树都不会改变,因为两者都是最小化一个和,但任何把权重与绝对阈值比较的统计量都会改变,而乘以负数则会把问题完全颠倒。第二,单位必须一致,才能把权重相加。在一个权重函数中混用分钟和公里,得到的数字没有任何算法能够解释,而代码也不会报错。

11. 常见错误

12. 术语表

术语含义
权重函数 w: E → ℝ为每条边指定一个数;它独立于 G = (V, E)
无权图等价于满足以下条件的带权图: w(e) = 1 处处成立
路径的权重按加性约定,为其各边权重之和
距离 d(u, v)从 u 到 v 的所有路径中的最小权重
瓶颈值路径上的最小边权;最宽路径将其最大化
负环总权重为负的环;使最短路径无定义
强度 s(v)v 处各边权重之和,即带权的度
最小生成树总权重最小的生成树;无权时是平凡的
重新赋权用势函数平移权重使其非负,如 Johnson 算法中的做法
阈值化只保留高于某个阈值的边,把带权图变成无权图

13. 常见问题

带权图和无权图有什么区别?

带权图在图 G = (V, E) 本身之外,还带有一个为每条边指定一个数的函数 w。无权图没有这样的函数,这等同于每条边的权重都是 1。实际的后果是,“最短路径”在无权情形下意味着边数最少,在带权情形下意味着总权重最小,而这两者往往是不同的路径。

可以在带权图上使用 BFS 吗?

可以运行,但它回答的是另一个问题:它返回边数最少的路径,完全忽略权重。这不是权重最小路径的近似,两者之间的差距没有上界。有两个真正的例外:如果所有权重都相等,BFS 是正确的,而且比 Dijkstra 更快;如果权重只有 0 和 1,基于双端队列的 0-1 BFS 能在线性时间内给出正确的带权答案。

为什么 Dijkstra 算法在有负权重时会失效?

因为它是贪心的:当它从优先队列中取出一个顶点时,就宣布这个距离是最终的,并且再也不回头检查。只有当延长路径不可能降低成本时,这才是正确的,而非负权重恰好保证了这一点。有了负权边,在顶点确定之后可能出现更便宜的路线,而这一改进会被丢弃。第 6 节给出了一个四顶点的例子,Dijkstra 返回 2,而真实距离是 -2。请改用 Bellman-Ford,全源问题则用 Johnson 算法。

在无权图中,最小生成树有意义吗?

没什么意义。有 n 个顶点的连通图,其每棵生成树恰有 n-1 条边,所以在权重相等时它们的总和都相同,每棵生成树都是最小的。任何一次 BFS 或 DFS 遍历都能在线性时间内得到一棵。只有当边的成本各不相同时,最小生成树问题才变得有趣,这也是 Kruskal 和 Prim 算法本质上是带权算法的原因。

权重会改变图是否连通吗?

不会。连通性、二部性、平面性、度序列和环结构都只是 (V, E) 的性质,而权重函数位于它之外。添加、删除或缩放权重都不会改变其中任何一项。如果某个带权计算似乎与结构性事实相矛盾,那么错误出在赋权或代码上,而不在理论上。

如何把概率或相似度当作权重处理?

先把它们转换为加性成本。对于概率,路径的值是其各边的乘积,而最大化乘积等同于最小化负对数之和,所以把 w 换成 -log w 再运行 Dijkstra:每个概率至多为 1,所以每个 -log w 都非负。对于相似度,要明确选定一种距离,例如 1 - s、1/s 或 -log s。把原始相似度直接交给最短路径程序,找到的是经过最不相似链接的路径,这几乎从来不是想要的结果。

14. 参考文献

以上定义、算法和归属均出自以下文献,按时间顺序排列。

  1. Borůvka, O. (1926). "O jistém problému minimálním"(关于某个极小问题)。 Práce Moravské Přírodovědecké Společnosti 3,37 至 58 页。最早的最小生成树算法。
  2. Kruskal, J. B. (1956). "On the Shortest Spanning Subtree of a Graph and the Traveling Salesman Problem." Proceedings of the American Mathematical Society 7(1),48 至 50 页。
  3. Prim, R. C. (1957). "Shortest Connection Networks and Some Generalizations." Bell System Technical Journal 36(6),1389 至 1401 页。
  4. Bellman, R. (1958). "On a Routing Problem." Quarterly of Applied Mathematics 16(1),87 至 90 页。能容许负权重的最短路径。
  5. Dijkstra, E. W. (1959). "A Note on Two Problems in Connexion with Graphs." Numerische Mathematik 1,269 至 271 页。文中明确提出了非负性假设。
  6. Moore, E. F. (1959). "The Shortest Path Through a Maze." Proceedings of an International Symposium on the Theory of Switching,第二部分,285 至 292 页。Harvard University Press。单位权重情形,即如今所说的 BFS。
  7. Johnson, D. B. (1977). "Efficient Algorithms for Shortest Paths in Sparse Networks." Journal of the ACM 24(1),1 至 13 页。通过重新赋权消除负权边。
  8. Fredman, M. L. and Tarjan, R. E. (1987). "Fibonacci Heaps and Their Uses in Improved Network Optimization Algorithms." Journal of the ACM 34(3),596 至 615 页。O(m + n log n) 的 Dijkstra。
  9. Ahuja, R. K., Magnanti, T. L. and Orlin, J. B. (1993). Network Flows: Theory, Algorithms, and Applications. Englewood Cliffs:Prentice Hall。关于以容量和成本为权重的标准参考书。
  10. Thorup, M. (1999). "Undirected Single-Source Shortest Paths with Positive Integer Weights in Linear Time." Journal of the ACM 46(3),362 至 394 页。
  11. West, D. B. (2001). Introduction to Graph Theory,第 2 版。Upper Saddle River:Prentice Hall。
  12. Barrat, A., Barthélemy, M., Pastor-Satorras, R. and Vespignani, A. (2004). "The Architecture of Complex Weighted Networks." Proceedings of the National Academy of Sciences 101(11),3747 至 3752 页。顶点强度的出处。
  13. Newman, M. E. J. (2004). "Analysis of Weighted Networks." Physical Review E 70,056131。标准网络指标的带权版本。
  14. Bondy, J. A. and Murty, U. S. R. (2008). Graph Theory. Graduate Texts in Mathematics 244。伦敦:Springer。第 1 节中带权图定义的出处。
  15. Cormen, T. H., Leiserson, C. E., Rivest, R. L. and Stein, C. (2009). Introduction to Algorithms,第 3 版。马萨诸塞州剑桥:MIT Press。
  16. Diestel, R. (2017). Graph Theory,第 5 版。Graduate Texts in Mathematics 173。柏林:Springer。

改变一个权重,看路径如何移动

构建第 3 节中的图,运行 Dijkstra,然后提高其中一条边的权重,再运行一次。亲眼看到路线跳变,胜过读再多相关文字。

打开可视化工具

改变一个权重,看路径移动

构建第 3 节中的图,运行 Dijkstra,然后提高其中一条边的权重,再运行一次。亲眼看到路线跳变,胜过读再多相关文字。

启动 Dijkstra 可视化工具