[TOC]
Dijkstra
- 1976. 到达目的地的方案数:计算到达每一个点的最短路径数(单源最短)
朴素Dijkstra
class Solution:
def countPaths(self, n: int, roads: List[List[int]]) -> int:
g = [[inf for _ in range(n)] for _ in range(n)] # 邻接矩阵
for x, y, d in roads:
g[x][y] = d
g[y][x] = d
dis = [inf] * n
dis[0] = 0
f = [0] * n
f[0] = 1
done = [False] * n
while True:
x = -1
for i, ok in enumerate(done):
if not ok and (x < 0 or dis[i] < dis[x]):
x = i
if x == n - 1: # 不可能找到比 dis[-1] 更短,或者一样短的最短路了(注意本题边权都是正数)
return f[-1]
done[x] = True # 最短路长度已确定(无法变得更小)
dx = dis[x]
for y, d in enumerate(g[x]): # 尝试更新 x 的邻居的最短路
new_dis = dx + d
if new_dis < dis[y]:
# 就目前来说,最短路必须经过 x
dis[y] = new_dis
f[y] = f[x]
elif new_dis == dis[y]:
# 和之前求的最短路一样长
f[y] = (f[y] + f[x]) % 1_000_000_007
堆Dijkstra
class Solution:
def countPaths(self, n: int, roads: List[List[int]]) -> int:
g = [[] for _ in range(n)] # 邻接表
for x, y, d in roads:
g[x].append((y, d))
g[y].append((x, d))
dis = [inf] * n
dis[0] = 0
f = [0] * n
f[0] = 1
h = [(0, 0)]
while True:
dx, x = heappop(h)
if x == n - 1:# 不可能找到比 dis[-1] 更短,或者一样短的最短路了(注意本题边权都是正数)
return f[-1]
if dx > dis[x]:
continue
for y, d in g[x]: # 尝试更新 x 的邻居的最短路
new_dis = dx + d
if new_dis < dis[y]:
# 就目前来说,最短路必须经过 x
dis[y] = new_dis
f[y] = f[x]
heappush(h, (new_dis, y))
elif new_dis == dis[y]:
# 和之前求的最短路一样长
f[y] = (f[y] + f[x]) % 1_000_000_007
题单
743. 网络延迟时间
2642. 设计可以求最短路径的图类 1811
1514. 概率最大的路径 1846
1631. 最小体力消耗路径 1948 做法不止一种
1368. 使网格图至少有一条有效路径的最小代价 2069 也可以 0-1 BFS
1786. 从第一个节点出发到最后一个节点的受限路径数 2079
1976. 到达目的地的方案数 2095
2662. 前往目标的最小代价 2154
2045. 到达目的地的第二短时间 2202 也可以 BFS
882. 细分图中的可到达节点 2328
2203. 得到要求路径的最小带权子图 2364
2577. 在网格图中访问一个格子的最少时间 2382
2699. 修改图中的边权 2874
2093. 前往目标城市的最小费用(会员题)
2473. 购买苹果的最低成本(会员题)
2714. 找到最短路径的 K 次跨越(会员题)
2737. 找到最近的标记节点(会员题)
LCP 35. 电动车游城市