前言
朴素Dijkstra适用于邻接矩阵,堆优化的Dijkstra适用于邻接表,SPFA适用于带有负权值边的图。
以上这三种都适用于单源最短路径求解。
Floy适用于任意两点最短路径求解
一、朴素Dijkstra
MAX_VALUE=999999999
n,o1=map(int,input().split())
#g是邻接矩阵。
d=[MAX_VALUE]*n
used=[False]*n
def dijkstra(s): #s是原点。
global d
global used
d[s]=0
while True:
v=-1
for i in range(n):
if not used[i] and( v==-1 or d[i]<d[v]):
v=i
if v==-1:
break
used[v]=True
for i in range(n):
d[i]=min(d[i],d[v]+g[v][i])
dijkstra(o1)
二、堆优化Dijkstra
import heapq
#edge[i]存储的是某个顶点的所有边的另一个顶点及权值
def dijk(edge,u,v): #u是原点,v是终点。
global ans
t=[(0,u)]
heapq.heapify(t)
visit=dict()
while t:
dis,y=heapq.heappop(t)
visit[y]=dis
if y==v:
ans=dis
break
for i,w in edge[y]:
if i not in visit:
heapq.heappush(t,(dis+w,i))
三、SPFA(可计算负权值边)
1.计算最短路径
n,o1=map(int,input().split())
#将输入的数据转化为字典的列表存储,边的信息,
edges = [ dict() for _ in range(n)]
#edges[i][j]表示i到j的值。
for i in range(n):
e=list(map(int,input().split()))
for j in range(len(e)):
if e[j]!=0:
edges[i][j]=e[j]
dis=[float('inf') for i in range(n)]
dis[o1]=0
line=[]
line.append(o1)
while len(line)!=0:
t=line[0]
#遍历该点的所有边,更新其后继点的距离
for next,weight in edges[t].items():
if dis[next]>dis[t]+weight:
dis[next]=dis[t]+weight
if next not in line:
line.append(next)
#若后继点不在队里,则入队。
line.remove(t)
2.判断是否有负环。
#判断是否有负环
n,o1=map(int,input().split())
#将输入的数据转化为字典的列表存储,边的信息,
edges = [ dict() for _ in range(n)]
#edges[i][j]表示i到j的值。
for i in range(n):
e=list(map(int,input().split()))
for j in range(len(e)):
if e[j]!=0:
edges[i][j]=e[j]
dis=[float('inf') for i in range(n)]
dis[o1]=0
line=[]
line.append(o1)
cnt=[0]*n
while len(line)!=0:
t=line[0]
#遍历该点的所有边,更新其后继点的距离
for next,weight in edges[t].items():
if dis[next]>dis[t]+weight:
dis[next]=dis[t]+weight
cnt[next] = cnt[t] + 1; #将当前点到起点的距离+1
if(cnt[next] >= n):#若走过的边数等于n,则有负环。关键
print("负环")#改为return
break
if next not in line:
line.append(next)
#若后继点不在队里,则入队。
line.remove(t)
四、Floy
def floya(g,m):
for k in range(m):
for i in range(m):
for j in range(m):
if g[i][k]!=MAX_value and g[k][j]!=MAX_value and g[i][k]+g[k][j]<g[i][j]:
g[i][j]=g[i][k]+g[k][j]
floya(g,n)