P5905 【模板】Johnson 全源最短路 题解

博客探讨了如何使用Johnson算法解决图中可能存在负环、负权、重边和自环情况下的任意两点最短路径问题。通过算法一的Floyd、算法二的Dijkstra优化以及算法三的详细解释,阐述了Johnson算法的原理和步骤,包括构造上帝节点、调整边权和SPFA与Dijkstra的结合应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

博客园同步

原题链接

前置知识:

dijkstra \text{dijkstra} dijkstra 模板

简要题意:

求任意两点的最短路。图中可能有 负环,负权,重边,自环 等现象。

显然我们先建图。

算法一

对于 20 % 20\% 20% 的数据, 1 ≤ n ≤ 100 1\leq n \leq 100 1n100,不存在负环(可用于验证 Floyd \text{Floyd} Floyd 正确性)

嗯,出题人都告诉你用 Floyd \text{Floyd} Floyd 了,而且 Floyd \text{Floyd} Floyd 的代码简洁得出奇,所以这 20 p t s 20pts 20pts 完全是送给你啦!

时间复杂度: O ( n 3 ) O(n^3) O(n3).

实际得分: 20 p t s 20pts 20pts.

算法二

对于另外 20 % 20\% 20% 的数据, w ≥ 0 w \geq 0 w0(可用于验证 Dijkstra \text{Dijkstra} Dijkstra 正确性)

出题人真善良,算法都告诉你了。

Dijkstra \text{Dijkstra} Dijkstra n n n 次,然后队列优化(不优化肯定连部分分都拿不到了)

时间复杂度: O ( n m log ⁡ n ) O(nm \log n) O(nmlogn).

实际得分: 40 p t s 40pts 40pts.(结合前面的 Floyd \text{Floyd} Floyd

算法三

我们基于 Dijkstra \text{Dijkstra} Dijkstra 的思路思考,因为这个思路不会超时,我们需要想一个办法解决 负环 问题。

可以想到的一种办法,把所有边权加上一个值使得不存在负权,然后再减回去。但是 理想是美好的,现实是残酷的 这样贪心完全错了。

比方说:

你先把每条边 + 3 +3 +3 变成:

求出最短路为 0 0 0. 然而正确的答案是 − 4 -4 4,你怎么减也减不出这个值。其错误在于,假设走了多条边的最短路与另一条走了较少边的次短路,加上值之后最短路就不一定还是最短路了。

这样要是能解决我们还要 Johnson \text{Johnson} Johnson 干么

他提出了一种思想,解决这种问题:

  • 构造一个“上帝节点” 0 0 0 号,并且建边 ( 0 , i , 0 ) ( 1 ≤ i ≤ n ) (0,i,0) (1 \leq i \leq n) (0,i,0)(1in).(即向每个点建一条权值为 0 0 0 的边)

  • SPFA \text{SPFA} SPFA 一遍求出 h i h_i hi 表示 0 0 0 号节点到 i i i 号节点的最短路(顺便可以判负环)。

  • 此时如果有一条 u → v u \rightarrow v u

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值