1.Dijkstra算法(单源最短路径)
例题:蓝桥王国
3 3
1 2 1
1 3 5
2 3 2
0 1 3
1.用到bfs和优先队列,每次从未标记的点中,选择距离出发点最近的节点,标记。
2.计算队列中弹出节点a的临近节点b,如果节点b从经过a这条路走的距离小于原来的,更新b的距离,把b也加入队列中
3.如果弹出的节点是打过标记的节点,直接跳过,因为此节点到起点的最短路径已找到。
from queue import *
n,m=map(int,input().split())
vis=[0 for i in range(n+1)]
d=[float("inf") for i in range(n+1)]
edge=[[]for i in range(m+1)]
for i in range(m):
u,v,w=map(int,input().split())
edge[u].append([w,v])
def dijkstra():
p=PriorityQueue()
p.put((0,1))
d[1]=0
while not p.empty():
q=p.get()
node,dis=q[1],q[0]
if vis[node]==1:
continue
vis[node]=1
for w,v in edge[node]:
if d[v]>dis+w:
d[v]=dis+w
p.put((d[v],v))
for i in range(1,n+1):
if d[i]==float("inf"):
print(-1)
else:
print(d[i],end=' ')
dijkstra()
2.Floyd 算法 多源最短路径
蓝桥公园
N=405
dp=[[float('inf') for i in range(N)]for j in range(N)]
def floyd():
for k in range(1,n+1):
for i in range(1,n+1):
for j in range(1,n+1):
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j])
n,m,p=map(int,input().split())
for j in range(m):
i,j,e=map(int,input().split())
dp[i][j]=dp[j][i]=e
floyd()
for i in range(p):
s,t=map(int,input().split())
if dp[s][t]==float('inf'):
print(-1)
if s==t:
print(0)
else:
print(dp[s][t])
3.SPFA算法(单源最短路径,边权为负)
- 起点 s 入队,计算它所有邻居到 s 的最短距离(当前最短距离,不是全局最短距离。下文中,把计算一个结点到起点 s 的最短路径简称为更新状态。最后的“状态”就是 SPFA 的计算结果)。把 s 出队,状态有更新的邻居入队,没更新的不入队。也就是说,队列中都是状态有变化的结点,只有这些结点才影响最短路径的计算。
- 现在队列的头部是 s 的一个邻居 u。弹出 u,更新它所有邻居的状态,把其中有状态变化的邻居入队列。
- 弹出 u 之后,在后面的计算中,u 可能会再次更新状态(后面 u 可能借道别的结点去 s,路更近),u 需要重新入队列。这一点很容易做到:处理一个新的结点 v 时,它的邻居可能就是以前处理过的 u,如果 u 的状态变化了,把 u 重新加入队列就行了。
- 继续以上过程,直到队列空。这也意味着,所有结点的状态都不再更新。最后的状态就是到起点 s 的最短路径。
from queue import *
n,m=map(int,input().split())
vis=[0 for i in range(n+1)]
d=[float("inf") for i in range(n+1)]
edge=[[]for i in range(m+1)]
for i in range(m):
u,v,w=map(int,input().split())
edge[u].append([w,v])
def spfa():
q=Queue()
q.put(1)
d[1]=0
vis[1]=1
while not q.empty():
p=q.get()
vis[p]=0
for dist,son in edge[p]:
if d[son]>d[p]+dist:
d[son]=d[p]+dist
if vis[son]==0:
q.put(son)
vis[son]=1
spfa()
for i in range(1,n+1):
if d[i]==float('inf'):
print(-1,end=' ')
else:
print(d[i],end=' ')