迪杰斯特拉(Dijkstra)算法

之前学了弗洛依达(Floyd)算法,类似于暴力搜索,但在有的算法题中可能会出现超时的状况。因此又去学了迪杰斯特拉算法。下边是我对这个算法所做的总结。包括初次尝试的失败案例。

简介:

迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。

算法思想:

迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法策略,每次遍历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止。

例题:

题目链接:用户登录icon-default.png?t=N7T8https://www.lanqiao.cn/problems/1122/learning/?page=1&first_category_id=1&second_category_id=8

1.题目描述:

蓝桥王国一共有N个建筑和M条单向道路,每条道路都连接着两个建筑,每个建筑都有自己的编号,分别为1~N。(其中皇宫编号为1)

国王想让小明回答从皇宫到每个建筑的最短距离是多少,但紧张的小明此时已经无法思考,请你编写程序帮助小明回答国王的考核。

2.输入描述:

输入第一行包含两个正整数N,M。

第2到M+1行每行包含三个正整数u,v,w,表示u->v之间存在一条距离为w的路。

3.输出描述:

输出仅一行,共N个数,分别表示从皇宫到编号为1~N建筑的最短距离,两两之间用空格隔开。(如果无法到达输出为-1)

举个简单例子:

1->2距离初始化为1

1->3距离初始化为5

2->3距离初始化为2

在实现的过程中,尽可能的找到一个中间点,尝试“绕路”寻找最短路径。比如1->3距离是5,但是我可以绕路,先从1走到2距离是1,再从2走到3,距离为2,更新1->3的距离,为3,比之前的5要小。

4.原始算法

import os
import sys
n,m=map(int,input().split())
ds=[[0x3f for j in range(n+1)] for i in range(n+1)]#ds存储点之间的距离
for i in range(1,m+1):
    u,v,w=map(int,input().split())
    ds[u][v]=min(ds[u][v],w)
d=[0x3f for i in range(n+1)]#d存储从节点1到节点n之间的距离
d[1]=0#节点1到自身的距离为0
st=[False for i in range(n+1)]#st标记节点是否使用过
for i in range(1,n+1):
    temp=-1
    for j in range(1,n+1):
        if not st[j] and(temp==-1 or d[j]<d[temp]):#寻找一个距离短的中间节点j
            temp=j
    st[temp]=True#标记节点使用过
    for i in range(1,n+1):
        d[i]=min(d[i],d[temp]+ds[temp][i])#更新节点间的距离
for i in range(1,n+1):
    print(f'{d[i]}',end=' ')

在提交的时候发现运行超时。

5.算法优化

import heapq
INF=float("inf")#INF表示无穷大
N,M=map(int,input().split())
dp[INF]*(N+1)#dp存储节点1到节点i的距离
a=[[] for _ in range(N+1)]#存储节点之间的距离
for i in range(1,M+1):
    u,v,w=map(int,input().split())
    a[u].append((v,w))
q=[]
heapq.heappush(q,(0,1))#(0,1)0表示距离,1表示节点,队列会自动按照第一维的值排序,所以距离0放在前边
dp[1]=0#表示节点1到自身距离为0
def dij():
    vis=[0 for i in range(N+1)]#标记节点是否用过
    while q:
        v=heapq.heappop(q)[1]
        if vis[v]==1:continue
        vis[v]=1
        for vnext,wnext in a[v]:
            if vsi[vnext]==1:continue
            vis[vnext]=1
            dp[vnext]=min(dp[vnext],dp[v]+wnext)
            heapq.heappush(q,(dp[vnext],vnext))
dij()
for i in range(N+1):
    if dp[i]==INF:
        print(-1,end=' ')
    else:
        print(dp[i],end=' ')

  • 18
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值