5.4 KiB
5.4 KiB
图论常见算法
Dijkstra算法
用于求解单个源最短路问题:
- 初始化:将所有顶点的距离设为正无穷,源顶点设为0;
- 迭代:从源顶点出发,遍历所有边,更新顶点的距离;
- 检验:检查是否存在负权重环,如果有则返回错误;
- 返回:返回所有顶点的距离。
Bellman-Ford算法
数学公式
对于图 $G=(V,E)$,Bellman-Ford算法通过迭代松弛更新每个顶点的最短路径估计:
d(v) = \min\{d(u) + w(u,v) | (u,v) \in E\}
其中:
d(v)是从源顶点到顶点v的最短路径估计w(u,v)是边(u,v)的权重- 迭代次数最多为
|V|-1次
Python实现
def bellman_ford(graph, source):
"""
Bellman-Ford算法求单源最短路径
参数:
graph: 邻接表表示的图,格式 {u: [(v, w), ...]}
source: 源顶点
返回:
distances: 各顶点到源顶点的最短距离
"""
# 初始化距离
distances = {v: float('inf') for v in graph}
distances[source] = 0
# 获取所有顶点
vertices = list(graph.keys())
# 最多进行 |V|-1 次迭代
for _ in range(len(vertices) - 1):
# 对每条边进行松弛操作
for u in graph:
for v, w in graph[u]:
if distances[u] != float('inf') and distances[u] + w < distances[v]:
distances[v] = distances[u] + w
# 检测负权重环
for u in graph:
for v, w in graph[u]:
if distances[u] != float('inf') and distances[u] + w < distances[v]:
raise ValueError("图中存在负权重环")
return distances
# 示例使用
if __name__ == "__main__":
# 构建图 (邻接表)
graph = {
'A': [('B', 4), ('C', 2)],
'B': [('C', 3), ('D', 2), ('E', 3)],
'C': [('B', 1), ('D', 4)],
'D': [('E', -5)], # 负权重边
'E': []
}
try:
distances = bellman_ford(graph, 'A')
print("Bellman-Ford 结果:", distances)
except ValueError as e:
print(e)
常用算法Python实现
1. Dijkstra算法
数学公式
Dijkstra算法维护一个优先队列,每次选取具有最小距离估计的顶点:
d(v) = \min_{u \in S} \{ d(u) + w(u,v) \}
其中 S 是已确定最短路径的顶点集合。
Python实现
import heapq
def dijkstra(graph, source):
"""
Dijkstra算法求单源最短路径
参数:
graph: 邻接表表示的图,格式 {u: [(v, w), ...]}
source: 源顶点
返回:
distances: 各顶点到源顶点的最短距离
"""
# 初始化距离
distances = {v: float('inf') for v in graph}
distances[source] = 0
# 优先队列: (距离, 顶点)
pq = [(0, source)]
visited = set()
while pq:
# 取出最小距离的顶点
current_dist, u = heapq.heappop(pq)
# 如果已访问则跳过
if u in visited:
continue
visited.add(u)
# 更新邻接顶点的距离
for v, w in graph.get(u, []):
if v not in visited and current_dist + w < distances[v]:
distances[v] = current_dist + w
heapq.heappush(pq, (distances[v], v))
return distances
# 示例使用
if __name__ == "__main__":
# 构建图 (邻接表)
graph = {
'A': [('B', 4), ('C', 2)],
'B': [('C', 3), ('D', 2), ('E', 3)],
'C': [('B', 1), ('D', 4)],
'D': [('E', 5)],
'E': []
}
distances = dijkstra(graph, 'A')
print("Dijkstra 结果:", distances)
# 输出: {'A': 0, 'B': 3, 'C': 2, 'D': 5, 'E': 8}
2. Bellman-Ford算法
数学公式
对于图 $G=(V,E)$,Bellman-Ford算法通过迭代松弛更新每个顶点的最短路径估计:
d(v) = \min\{d(u) + w(u,v) | (u,v) \in E\}
其中:
d(v)是从源顶点到顶点v的最短路径估计w(u,v)是边(u,v)的权重- 迭代次数最多为
|V|-1次
Python实现
def bellman_ford(graph, source):
"""
Bellman-Ford算法求单源最短路径
参数:
graph: 邻接表表示的图,格式 {u: [(v, w), ...]}
source: 源顶点
返回:
distances: 各顶点到源顶点的最短距离
"""
# 初始化距离
distances = {v: float('inf') for v in graph}
distances[source] = 0
# 获取所有顶点
vertices = list(graph.keys())
# 最多进行 |V|-1 次迭代
for _ in range(len(vertices) - 1):
# 对每条边进行松弛操作
for u in graph:
for v, w in graph[u]:
if distances[u] != float('inf') and distances[u] + w < distances[v]:
distances[v] = distances[u] + w
# 检测负权重环
for u in graph:
for v, w in graph[u]:
if distances[u] != float('inf') and distances[u] + w < distances[v]:
raise ValueError("图中存在负权重环")
return distances
# 示例使用
if __name__ == "__main__":
# 构建图 (邻接表)
graph = {
'A': [('B', 4), ('C', 2)],
'B': [('C', 3), ('D', 2), ('E', 3)],
'C': [('B', 1), ('D', 4)],
'D': [('E', -5)], # 负权重边
'E': []
}
try:
distances = bellman_ford(graph, 'A')
print("Bellman-Ford 结果:", distances)
except ValueError as e:
print(e)