【最短路问题】

前言

朴素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)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值