LeetCode 题解工作台
最短路径中的边
给你一个 n 个节点的无向带权图,节点编号为 0 到 n - 1 。图中总共有 m 条边,用二维数组 edges 表示,其中 edges[i] = [a i , b i , w i ] 表示节点 a i 和 b i 之间有一条边权为 w i 的边。 对于节点 0 为出发点,节点 n - 1 为结束点…
5
题型
4
代码语言
3
相关题
当前训练重点
困难 · 图·DFS·traversal
答案摘要
我们先创建一个邻接表 ,用于存储图的边。然后创建一个数组 ,用于存储从节点 到其他节点的最短距离。初始化 $dist[0] = 0$,其余节点的距离初始化为无穷大。 然后,我们使用 Dijkstra 算法计算从节点 到其他节点的最短距离。具体步骤如下:
Interview AiBoxInterview AiBox 实时 AI 助手,陪你讲清 图·DFS·traversal 题型思路
题目描述
给你一个 n 个节点的无向带权图,节点编号为 0 到 n - 1 。图中总共有 m 条边,用二维数组 edges 表示,其中 edges[i] = [ai, bi, wi] 表示节点 ai 和 bi 之间有一条边权为 wi 的边。
对于节点 0 为出发点,节点 n - 1 为结束点的所有最短路,你需要返回一个长度为 m 的 boolean 数组 answer ,如果 edges[i] 至少 在其中一条最短路上,那么 answer[i] 为 true ,否则 answer[i] 为 false 。
请你返回数组 answer 。
注意,图可能不连通。
示例 1:

输入:n = 6, edges = [[0,1,4],[0,2,1],[1,3,2],[1,4,3],[1,5,1],[2,3,1],[3,5,3],[4,5,2]]
输出:[true,true,true,false,true,true,true,false]
解释:
以下为节点 0 出发到达节点 5 的 所有 最短路:
- 路径
0 -> 1 -> 5:边权和为4 + 1 = 5。 - 路径
0 -> 2 -> 3 -> 5:边权和为1 + 1 + 3 = 5。 - 路径
0 -> 2 -> 3 -> 1 -> 5:边权和为1 + 1 + 2 + 1 = 5。
示例 2:

输入:n = 4, edges = [[2,0,1],[0,1,1],[0,3,4],[3,2,2]]
输出:[true,false,false,true]
解释:
只有一条从节点 0 出发到达节点 3 的最短路 0 -> 2 -> 3 ,边权和为 1 + 2 = 3 。
提示:
2 <= n <= 5 * 104m == edges.length1 <= m <= min(5 * 104, n * (n - 1) / 2)0 <= ai, bi < nai != bi1 <= wi <= 105- 图中没有重边。
解题思路
方法一:堆优化的 Dijkstra
我们先创建一个邻接表 ,用于存储图的边。然后创建一个数组 ,用于存储从节点 到其他节点的最短距离。初始化 ,其余节点的距离初始化为无穷大。
然后,我们使用 Dijkstra 算法计算从节点 到其他节点的最短距离。具体步骤如下:
- 创建一个优先队列 ,用于存储节点的距离和节点编号,初始时将节点 加入队列,距离为 。
- 从队列中取出一个节点 ,如果 的距离 大于 ,说明 已经被更新过了,直接跳过。
- 遍历节点 的所有邻居节点 ,如果 ,则更新 ,并将节点 加入队列。
- 重复步骤 2 和步骤 3,直到队列为空。
接着,我们创建一个长度为 的答案数组 ,初始时所有元素都为 。如果 为无穷大,说明节点 无法到达节点 ,直接返回 。否则,我们从节点 开始,遍历所有的边,如果边 满足 ,则将 置为 ,并将节点 加入队列。
最后,返回答案即可。
时间复杂度 ,空间复杂度 ,其中 和 分别为节点数和边数。
class Solution:
def findAnswer(self, n: int, edges: List[List[int]]) -> List[bool]:
g = defaultdict(list)
for i, (a, b, w) in enumerate(edges):
g[a].append((b, w, i))
g[b].append((a, w, i))
dist = [inf] * n
dist[0] = 0
q = [(0, 0)]
while q:
da, a = heappop(q)
if da > dist[a]:
continue
for b, w, _ in g[a]:
if dist[b] > dist[a] + w:
dist[b] = dist[a] + w
heappush(q, (dist[b], b))
m = len(edges)
ans = [False] * m
if dist[n - 1] == inf:
return ans
q = deque([n - 1])
while q:
a = q.popleft()
for b, w, i in g[a]:
if dist[a] == dist[b] + w:
ans[i] = True
q.append(b)
return ans
复杂度分析
| 指标 | 值 |
|---|---|
| 时间 | Depends on the final approach |
| 空间 | Depends on the final approach |
面试官常问的追问
外企场景- question_mark
They mention shortest paths from both node 0 and node n - 1, which points directly to dual Dijkstra distances.
- question_mark
They care about whether an edge is on any shortest path, not about reconstructing one path, so edge validation is enough.
- question_mark
They highlight weighted edges and large constraints, which rules out BFS layering and brute-force DFS enumeration.
常见陷阱
外企场景- error
Running BFS because the graph is undirected, then getting wrong answers when weights differ.
- error
Only checking distFromStart[u] + w + distFromEnd[v] and forgetting the reverse orientation of the same undirected edge.
- error
Trying to store every predecessor path explicitly, which can explode on graphs with many tied shortest routes.
进阶变体
外企场景- arrow_right_alt
Return all nodes that lie on at least one shortest path by checking distFromStart[x] + distFromEnd[x] == best.
- arrow_right_alt
Count how many shortest paths use each edge, which requires DP over the shortest-path DAG instead of a simple boolean test.
- arrow_right_alt
Handle a directed version where each edge is checked in only its original direction after forward and reverse shortest-path runs.