关键词:Bellman-ford、队列、O(k*e) k为常数、能处理负权边、能判定负权回路
## n: 点数
## m: 边数
## u[]: 边的起点
## v[]: 边的终点
## w[]: 边的权值
## dis[n]: 各点到源点的最短路径
## Q[j]: 队列,初始时将源点加入队列
## vis[n]: 记录各点是否在队列中
##
## 思想:每次从队列中取出一点,根据此点的出边对相关点进行修正,同时将修正点放入队列,直至队列为空。
## 和广度优先算法类似,区别为曾经出队的点可能再入队。
## 初始化:dis[s]=0, dis[其他]=无穷大, Q.append(s), vis[s]=1, vis[其他]=0
##
def SPFA():
Q.append(s)
vis[s]=1
while(len(Q)):
item=Q.pop()
for i in range(m): ## 遍历图中的每条边
if u[i]==item: ## 找到起点为item的边
if dis[v[i]] > dis[u[i]] + w[i]:
dis[v[i]] = dis[u[i]] + w[i] ## 对第i条边的终点v[i]进行修正
if vis[v[i]]==0: ## 若终点v[i]不在队列中
Q.append(v[i]) ##则将终点v[i]入队
vis[v[i]]==1
## 在此基础上,还可以对算法进一步的优化
## 1.在输入u,v,w时同时将这三值存入g[u].append((v,w))中——>类似链表存储
## 2.设置无穷大时,先用INF=float("inf"),之后使用INF。以此来减少每次计算无穷大的时间
## 3.将list改成优先权队列heapq(顺序不影响的情况下)
import heapq
INF=float("inf")
def SPFA():
heapq.heappush(Q,s)
vis[s]=1
while(len(Q)):
u=heapq.heappop(Q) ## u: 当前点
for v,w in g[u]: ## 遍历图中的起点为u的边
if dis[v] > dis[u] + w:
dis[v] = dis[u] + w ## 对第i条边的终点v进行修正
if vis[v]==0: ## 若终点v[i]不在队列中
heapq.heappush(Q,v) ##则将终点v入队
vis[v]==1