python数据结构与算法——图的最短路径(Bellman-Ford算法)解决负权边

 1 # Bellman-Ford核心算法
 2 # 对于一个包含n个顶点,m条边的图, 计算源点到任意点的最短距离
 3 # 循环n-1轮,每轮对m条边进行一次松弛操作
 4
 5 # 定理:
 6 # 在一个含有n个顶点的图中,任意两点之间的最短路径最多包含n-1条边
 7 # 最短路径肯定是一个不包含回路的简单路径(回路包括正权回路与负权回路)
 8 # 1. 如果最短路径中包含正权回路,则去掉这个回路,一定可以得到更短的路径
 9 # 2. 如果最短路径中包含负权回路,则每多走一次这个回路,路径更短,则不存在最短路径
10 # 因此最短路径肯定是一个不包含回路的简单路径,即最多包含n-1条边,所以进行n-1次松弛即可
11
12
13 G = {1:{1:0, 2:-3, 5:5},
14      2:{2:0, 3:2},
15      3:{3:0, 4:3},
16      4:{4:0, 5:2},
17      5:{5:0}}
18
19
20
21 def getEdges(G):
22     """ 输入图G,返回其边与端点的列表 """
23     v1 = []     # 出发点
24     v2 = []     # 对应的相邻到达点
25     w  = []     # 顶点v1到顶点v2的边的权值
26     for i in G:
27         for j in G[i]:
28             if G[i][j] != 0:
29                 w.append(G[i][j])
30                 v1.append(i)
31                 v2.append(j)
32     return v1,v2,w
33
34 class CycleError(Exception):
35     pass
36
37 def Bellman_Ford(G, v0, INF=999):
38     v1,v2,w = getEdges(G)
39
40     # 初始化源点与所有点之间的最短距离
41     dis = dict((k,INF) for k in G.keys())
42     dis[v0] = 0
43
44     # 核心算法
45     for k in range(len(G)-1):   # 循环 n-1轮
46         check = 0           # 用于标记本轮松弛中dis是否发生更新
47         for i in range(len(w)):     # 对每条边进行一次松弛操作
48             if dis[v1[i]] + w[i] < dis[v2[i]]:
49                 dis[v2[i]] = dis[v1[i]] + w[i]
50                 check = 1
51         if check == 0: break
52
53     # 检测负权回路
54     # 如果在 n-1 次松弛之后,最短路径依然发生变化,则该图必然存在负权回路
55     flag = 0
56     for i in range(len(w)):             # 对每条边再尝试进行一次松弛操作
57         if dis[v1[i]] + w[i] < dis[v2[i]]:
58             flag = 1
59             break
60     if flag == 1:
61 #         raise CycleError()
62         return False
63     return dis
64
65 v0 = 1
66 dis = Bellman_Ford(G, v0)
67 print dis.values()
时间: 2024-09-27 04:05:09

python数据结构与算法——图的最短路径(Bellman-Ford算法)解决负权边的相关文章

python数据结构与算法——图的最短路径(Dijkstra算法)

1 # Dijkstra算法——通过边实现松弛 2 # 指定一个点到其他各顶点的路径——单源最短路径 3 4 # 初始化图参数 5 G = {1:{1:0, 2:1, 3:12}, 6 2:{2:0, 3:9, 4:3}, 7 3:{3:0, 5:5}, 8 4:{3:4, 4:0, 5:13, 6:15}, 9 5:{5:0, 6:4}, 10 6:{6:0}} 11 12 13 # 每次找到离源点最近的一个顶点,然后以该顶点为重心进行扩展 14 # 最终的到源点到其余所有点的最短路径 15

python数据结构与算法——图的最短路径(Floyd-Warshall算法)

使用Floyd-Warshall算法 求图两点之间的最短路径 不允许有负权边,时间复杂度高,思路简单 1 # 城市地图(字典的字典) 2 # 字典的第1个键为起点城市,第2个键为目标城市其键值为两个城市间的直接距离 3 # 将不相连点设为INF,方便更新两点之间的最小值 4 INF = 99999 5 G = {1:{1:0, 2:2, 3:6, 4:4}, 6 2:{1:INF, 2:0, 3:3, 4:INF}, 7 3:{1:7, 2:INF, 3:0, 4:1}, 8 4:{1:5, 2

最短路径——Bellman Ford算法(C++)

源代码: #include<cstdio>#include<cstring>int m(1),n,k,i[1001],x[1001],y[1001],f[1001];int main(){ scanf("%d%d",&n,&k); for (int a=1;a<=n;a++) for (int b=1;b<=n;b++) { scanf("%d",&i[m]); if (i[m]!=-1) { x[m]=a

Bellman—Ford算法思想

---恢复内容开始--- Bellman—Ford算法能在更普遍的情况下(存在负权边)解决单源点最短路径问题.对于给定的带权(有向或无向)图G=(V,E),其源点为s,加权函数w是边集E的映射.对图G运行Bellman—Ford算法的结果是一个布尔值,表明图中是否存在着一个从源点s可达的负权回路.若存在负权回路,单源点最短路径问题无解:若不存在这样的回路,算法将给出从源点s到图G的任意顶点v的最短路径值d[v] Bellman—Ford算法流程 分为三个阶段: (1)初始化:将除源点外的所有顶点

Bellman - Ford 算法解决最短路径问题

Bellman - Ford 算法: 一:基本算法 对于单源最短路径问题,上一篇文章中介绍了 Dijkstra 算法,但是由于 Dijkstra 算法局限于解决非负权的最短路径问题,对于带负权的图就力不从心了,而Bellman - Ford算法可以解决这种问题. Bellman - Ford 算法可以处理路径权值为负数时的单源最短路径问题.设想可以从图中找到一个环路且这个环路中所有路径的权值之和为负.那么通过这个环路,环路中任意两点的最短路径就可以无穷小下去.如果不处理这个负环路,程序就会永远运

[ACM] POJ 3259 Wormholes (bellman-ford最短路径,判断是否存在负权回路)

Wormholes Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 29971   Accepted: 10844 Description While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way p

贪心算法-图的最短路径算法Dijkstra之证明

一.问题:图的最短路径 定义图G=(V,E),而且每条边上的权值非负,求顶点s 到图中任意一点的最短距离.图中任意两点之间的距离定义为:路径上所有边的权值的和. 二.算法:Dijkstra算法 设S是探查的顶点的集合,对每个,我们存储一个距离d(u) 初始S={s},d(s)=0 While S != V 选择一个顶点使得从S到v至少有一条边并且 把v加入到S并且定义 End 三.证明算法的正确性: 只需证明,在算法执行中任意一点的集合S,对每个,路径是最短的s-u路径. 用数学归纳法证明算法的

ACM/ICPC 之 最短路径-Bellman Ford范例(POJ1556-POJ2240)

两道Bellman Ford解最短路的范例,Bellman Ford只是一种最短路的方法,两道都可以用dijkstra, SPFA做. Bellman Ford解法是将每条边遍历一次,遍历一次所有边可以求得一点到任意一点经过一条边的最短路,遍历两次可以求得一点到任意一点经过两条边的最短路...如 此反复,当遍历m次所有边后,则可以求得一点到任意一点经过m条边后的最短路(有点类似离散数学中邻接矩阵的连通性判定) POJ1556-The Doors 初学就先看POJ2240吧 题意:求从(0,5)到

poj 3259 Wormholes (BELLman—FOrd算法)(邻接矩阵表示)

http://poj.org/problem?id=3259 之前一开始 ,没做出来,搁置了好几天才看见bug所在.所以今天a掉了 ,把代码贴出来,这个使用邻接矩阵表示的 ,下一篇用邻接表可以提高效率. #include<iostream> #include<queue> #include<stdio.h> #include<string.h> using namespace std; const int INF=600; int G[INF][INF];