📅  最后修改于: 2023-12-03 14:58:19.713000             🧑  作者: Mango
这道问题考察了对于图遍历的基础知识,需要找到从给定起点到给定终点的最短路径。
给定一个无向图 $G=(V,E)$,每一条边 $e \in E$ 都有权重 $c(e)$,且对于 $1 \leq i,j \leq n$,若 $(i,j) \notin E$,则 $c(i,j)=\infty$。给定起点 $s$ 和终点 $t$,请实现一个算法来找到 $s$ 到 $t$ 的最短路径。
本题可以通过 Dijkstra 算法来解决。Dijkstra 算法的基本思想是维护一个集合 $S$,它包含已经找到最短路径的点,以及与这些点相邻的点。一开始, $S$ 只包含起点 $s$,并且到所有点的距离都为无穷大。随着算法的进行,将新的点加入到 $S$ 中,并更新与 $S$ 中的点相邻的点的距离。不断迭代这个过程,直到终点 $t$ 被加入到 $S$ 中,或者所有点都已加入。
具体实现时,可以使用一个优先队列来保存距离当前点最近的点。在每次从队列中取出一个点后,更新与该点相邻的点的距离,然后将它们加入到队列中。
最终,如果要输出路径,需要在更新过程中维护一个前驱数组 $p$,保存每一个点的前驱。
以下是使用 Python 语言实现 Dijkstra 算法的代码:
import heapq
def dijkstra(n, adj, s, t):
d = [float('inf')] * n
d[s] = 0
p = [-1] * n
q = []
heapq.heappush(q, (0, s))
while q:
dist, u = heapq.heappop(q)
if u == t:
break
if d[u] < dist:
continue
for v, w in adj[u]:
if d[u] + w < d[v]:
d[v] = d[u] + w
p[v] = u
heapq.heappush(q, (d[v], v))
if d[t] == float('inf'):
return []
else:
path = []
while t != -1:
path.append(t)
t = p[t]
return path[::-1]
其中,n 表示节点数,adj 是图的邻接表表示,s 表示起点,t 表示终点。邻接表的形式为:
adj = [[] for _ in range(n)]
for i in range(m):
u, v, w = map(int, input().split())
adj[u-1].append((v-1, w))
adj[v-1].append((u-1, w))
对于每个节点,邻接表中存储了与它相邻的点及其权重。
使用方式为:
path = dijkstra(n, adj, s, t)
if path:
print(*path)
else:
print(-1)
如果找到了最短路径,输出路径经过的节点;否则输出 -1。
Dijkstra 算法的时间复杂度为 $O((m+n)\log n)$,其中 $m$ 是边数,$n$ 是点数。邻接表的适用性弥补了邻接矩阵的空间复杂度问题,使得算法的总体表现更优秀。