## 图论常见算法 ### Dijkstra算法 用于求解单个源最短路问题: 1. 初始化:将所有顶点的距离设为正无穷,源顶点设为0; 2. 迭代:从源顶点出发,遍历所有边,更新顶点的距离; 3. 检验:检查是否存在负权重环,如果有则返回错误; 4. 返回:返回所有顶点的距离。 ### 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实现 ```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实现 ```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实现 ```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) ```