Python 最短路径的几种求解方式

目录
  • 前言
  • 前置知识
  • 练习题
    • 【单源最短路&迪杰斯特拉】畅通工程(续)
    • 【单源最短路 & spfa】最短路径
    • 【多源最短路 & 弗洛伊德】牛牛聚会

前言

给出几个点的名称,在给出几个点的路径权重(简称路权)就可以计算一个地图中最短的路权
是不是感觉很神奇。当然啦博主也觉得很神奇,因为博主比较笨嘛,如果只有几个点的图集的话
还可以口算出来图中的最短路,如果有上千个点的话,博主的大脑就不够用了。所以呢咱们掌握最
短路算法还是必须的,至少可以减少我们的脑力劳动嘛。

前置知识

图的话可以大致分为有向图与无向图、图中的边有的是正权值,有的是负权值
有的是两点之间多条路,有的甚至有自环(可以说是灰常的灵活)
创建一个图可以用的数据结构有:
十字链表、邻接多重表、邻接矩阵、边集数组、邻接表
本篇博客前两题解题方法使用的是邻接表,最后一个使用的是邻接矩阵
大家根据自己的喜好进行选择即可,但是思想还是一样的
如果大家对最短路不是很熟的话,推荐大家去看看这个UP主的视频,感觉讲的贼好传送门已就绪

十字链表:是有向图存储的一种链式存储结构,可以看成是有向图的邻接表和逆邻接表合起来得到的链表。用十字链表来存储有向图,可以达到高效的存取效果。同时,代码的可读性也会得到提升。

邻接多重表:邻接多重表是无向图的一种存储方式。邻接多重表是邻接表的改进,它把边的两个顶点存放在边表结点中,所有依附于同一个顶点的边串联在同一链表中,由于每条边依附于两个顶点,则每个边表结点同时链接在两个链表中

邻接矩阵:是表示顶点之间相邻关系的矩阵(个人感觉也是最简单的一个,但非常不适合稀疏图)逻辑结构分为两部分:V和E集合,其中,V是顶点,E是边。因此,用一个一维数组存放图中所有顶点数据;用一个二维数组存放顶点间关系(边或弧)的数据,这个二维数组称为邻接矩阵。邻接矩阵又分为有向图邻接矩阵和无向图邻接矩阵

边集数组:边集数组(edgeset array)是利用一维数组存储图中所有边的一种图的表示方法。该数组中所含元素的个数要大于等于图中边的条数,每个元素用来存储一条边的起点、终点(对于无向图,可选定边的任一端点为起点或终点)和权(若有的话),各边在数组中的次序可任意安排,也可根据具体要求而定。

知识介绍到此,下面上练习题吧

练习题

【单源最短路&迪杰斯特拉】畅通工程(续)

问题描述

Problem Description
某省自从实行了很多年的畅通工程计划后,终于修建了很多路。不过路多了也不好,每次要从一个城镇到另一个城镇时,
都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多。这让行人很困扰。
现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。
Input
本题目包含多组数据,请处理到文件结束。
每组数据第一行包含两个正整数N和M(0<N<200,0<M<1000),分别代表现有城镇的数目和已修建的道路的数目。城镇分别以0~N-1编号。
接下来是M行道路信息。每一行有三个整数A,B,X(0<=A,B<N,A!=B,0<X<10000),表示城镇A和城镇B之间有一条长度为X的双向道路。
再接下一行有两个整数S,T(0<=S,T<N),分别代表起点和终点。
Output
对于每组数据,请在一行里输出最短需要行走的距离。如果不存在从S到T的路线,就输出-1.
Sample Input
3 3
0 1 1
0 2 3
1 2 1
0 2
3 1
0 1 1
1 2
Sample Output
2
-1

问题分析

本题目中求解的是单源最短路,经过观察路的边权均是正的,所以我们暂定使用迪杰斯特拉算法
回顾一下迪杰斯特拉算法的模板步骤:

① 设置一个最短距离数组dis(存储某点到任一点的最短距离)
一个父节点数组pre(最短距离访问该节点需要首先访问的那个节点)
一个标记某点是否找到了最短路的列表visit
一个图(可以使用邻接多重表将边初始化进图G)
② 将出发点初始化一下
③ 选出没有被确定最短路的点中,距离源点最近的点
④ 使用他的边集优化边中点的最短距离
⑤ 将该点加入已找到最短路的数组

代码实现

n,m=map(int,input().split())
visit=[False]*(n+1)
dis=[1e8]*(n+1)
side=[list(map(int,input().split())) for i in range(m)]
G={k:[] for k in range(n)}
# s是起点e是终点
s,e=map(int,input().split())
# 初始化邻接表
for i in side:
    G[i[0]].append([i[1],i[2]])
    G[i[1]].append([i[0],i[2]])

dis[s]=0
for _ in range(n):
    mi=1e8
    for i in range(1,len(dis)):
        if dis[i]<mi and not visit[i]:
            mi=dis[i]
            s=i
    for i in G[s]:
        if dis[i[0]]>dis[s]+i[1]:
            dis[i[0]]=dis[s]+i[1]
    visit[s]=True

print(dis[e])

【单源最短路 & spfa】最短路径

问题描述

资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
给定一个n个顶点,m条边的有向图(其中某些边权可能为负,但保证没有负环)。请你计算从1号点到其他点的最短路(顶点从1到n编号)。
输入格式
第一行两个整数n, m。
接下来的m行,每行有三个整数u, v, l,表示u到v有一条长度为l的边。
输出格式
共n-1行,第i行表示1号点到i+1号点的最短路。
样例输入
3 3
1 2 -1
2 3 -1
3 1 2
样例输出
-1
-2
数据规模与约定
对于10%的数据,n = 2,m = 2。
对于30%的数据,n <= 5,m <= 10。
对于100%的数据,1 <= n <= 20000,1 <= m <= 200000,-10000 <= l <= 10000,保证从任意顶点都能到达其他所有顶点。

问题分析

spfa是一种随机方法,有些数据可能会将其卡死。他的思想是使用队列进行算法优化
特点是可以求含有负边权图的最短路。每次将更新过最短长度的点加入队列中(因为该点最短路更新了那么与他相连的点最短路也可能更新)然后从队列中每次取出一个点,对该点所连的点进行边权更新。然后将更新后的点再加入队列中,直到没有点更新为止。

代码实现

def spfa(n):
    # 存储修改过最短路权的点
    t=[]
    t.append(n)
    visit[n]=1
    while t:
        # 每次获取一个更新过路权的点
        temp=t.pop()
        # 更新与他相连点的路权
        for i in G[temp]:
            if dis[i[0]]>dis[temp]+i[1]:
                dis[i[0]]=dis[temp]+i[1]
                # 被更新过点所连得点也需要更新,所以将该点加入临时队列
                if visit[i[0]]==0:
                    visit[i[0]]=1
                    t.append(i[0])
n,m=map(int,input().split())
ls=[list(map(int,input().split())) for i in range(m)]
G={k:[] for k in range(1,n+1)}
for i in ls:
    G[i[0]].append([i[1],i[2]])
visit=[0]*(n+1)
dis=[1e8]*(n+1)
dis[1]=0
spfa(1)
print(dis)

【多源最短路 & 弗洛伊德】牛牛聚会

问题描述

给出n个点和m条边,接着是m条边,代表从牛a到牛b需要花费c时间,现在所有牛要到牛x那里去参加聚会,
并且所有牛参加聚会后还要回来,给你牛x,除了牛x之外的牛,他们都有一个参加聚会并且回来的最短时间,
从这些最短时间里找出一个最大值输出
Input
Line 1: Three space-separated integers, respectively: N, M, and X
Lines 2… M+1: Line i+1 describes road i with three space-separated integers:
Ai, Bi, and Ti. The described road runs from farm Ai to farm Bi, requiring Ti time units to traverse.
Output
Line 1: One integer: the maximum of time any one cow must walk.
Examples
Sample Input
4 8 2
1 2 4
1 3 2
1 4 7
2 1 1
2 3 5
3 1 2
3 4 4
4 2 3
Sample Output
10

问题分析

不妨先回忆一下怎么使用弗洛伊德算法:

① 构造两个图G(用于存储边权) P(用于存储父节点或者说用于存储先驱节点)
② 三层循环,判断两点之间最短路是否需要加边
得到的最短路放在G列表中
得到的最短路路径放在P数组中

代码实现

def F(n):
    for i in range(1,n+1):
        for j in range(1,n+1):
            for k in range(1,n+1):
                if G[i][j]>G[i][k]+G[k][j]:
                    G[i][j]=G[i][k]+G[k][j]
                    P[i][j]=k

n,m,x=map(int,input().split())
G=[[1e7 if i!=j else 0 for i in range(n+1)] for j in range(n+1)]
P=[[-1 if i==j else i  for i in range(n+1)] for j in range(n+1)]
ls=[list(map(int,input().split())) for i in range(m)]
for i in ls:
    G[i[0]][i[1]]=i[2]
F(n)
for i in G:
    print(i)
for i in P:
    print(i)
ans=[]
for i in range(1,n+1):
    if i==x:
        continue
    if G[i][x]!=1e7 and G[x][i]!=1e7:
        ans.append(G[i][x]+G[x][i])
print(ans)
print(max(ans))

到此这篇关于Python 最短路径的几种求解方式的文章就介绍到这了,更多相关Python 最短路径 内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Python实现最短路径问题的方法

    目录 一.创建图 二.问题来源 三.Dijkstra算法 四.Floyd算法 五.代码测试 一.创建图 在开始之前,我们先创建一个图,使用邻接矩阵表示有向网: class Graph(object): """ 以邻接矩阵为存储结构创建有向网 """ def __init__(self, kind): # 图的类型: 无向图, 有向图, 无向网, 有向网 # kind: Undigraph, Digraph, Undinetwork, Dinetw

  • python3实现Dijkstra算法最短路径的实现

    问题描述 现有一个有向赋权图.如下图所示: 问题:根据每条边的权值,求出从起点s到其他每个顶点的最短路径和最短路径的长度. 说明:不考虑权值为负的情况,否则会出现负值圈问题. s:起点 v:算法当前分析处理的顶点 w:与v邻接的顶点 d v d_v dv​:从s到v的距离 d w d_w dw​:从s到w的距离 c v , w c_{v,w} cv,w​:顶点v到顶点w的边的权值 问题分析 Dijkstra算法按阶段进行,同无权最短路径算法(先对距离为0的顶点处理,再对距离为1的顶点处理,以此类

  • python实现最短路径的实例方法

    最短路径问题(python实现) 解决最短路径问题:(如下三种算法) (1)迪杰斯特拉算法(Dijkstra算法) (2)弗洛伊德算法(Floyd算法) (3)SPFA算法 第一种算法: Dijkstra算法 广度优先搜索解决赋权有向图或者无向图的单源最短路径问题.是一种贪心的策略 算法的思路 声明一个数组dis来保存源点到各个顶点的最短距离和一个保存已经找到了最短路径的顶点的集合:T,初始时,原点s的路径权重被赋为0(dis[s]=0).若对于顶点s存在能直接到达的边(s,m),则把dis[m

  • Python使用Dijkstra算法实现求解图中最短路径距离问题详解

    本文实例讲述了Python使用Dijkstra算法实现求解图中最短路径距离问题.分享给大家供大家参考,具体如下: 这里继续前面一篇<Python基于Floyd算法求解最短路径距离问题>的内容,这里要做的是Dijkstra算法,与Floyd算法类似,二者的用途均为求解最短路径距离,在图中有着广泛的应用,二者的原理都是老生常谈了,毕竟本科学习数据结构的同学是不可能不学习这两个算法的,所以在这里我也不再累赘,只简单概述一下这个算法的核心思想: Dijkstra算法的输入有两个参数,一个是原始的数据矩

  • python3实现无权最短路径的方法

    问题描述 现有一个有向无权图.如下图所示: 问题:使用某个顶点s作为输入参数,找出从s到所有其他顶点的最短路径. 说明:因为是无权图,因此我们可以为每台边赋值为1.这里选择v3为s作为起点. 问题分析 此时立刻可以说,从s到v3的最短路径是长为0的路径,标记此信息,得到下图. 现在开始寻找从s出发距离为1的顶点.这些顶点肯定是与s邻接的顶点,很明显,v1,v6从s出发只需要一条边就到了.所以,从s出发距离为1的顶点,为v1,v6. 现在开始寻找从s出发距离为2的顶点.这些顶点肯定是与v1,v6(

  • Python实现的多叉树寻找最短路径算法示例

    本文实例讲述了Python实现的多叉树寻找最短路径算法.分享给大家供大家参考,具体如下: 多叉树的最短路径: 思想: 传入start 和 end 两个 目标值     1 找到从根节点到目标节点的路径     2 从所在路径,寻找最近的公共祖先节点,     3 对最近公共祖先根节点 拼接路径 Python代码: # -*- coding:utf-8 -*- import copy #节点数据结构 class Node(object): # 初始化一个节点 def __init__(self,v

  • python Dijkstra算法实现最短路径问题的方法

    本文借鉴于张广河教授主编的<数据结构>,对其中的代码进行了完善. 从某源点到其余各顶点的最短路径 Dijkstra算法可用于求解图中某源点到其余各顶点的最短路径.假设G={V,{E}}是含有n个顶点的有向图,以该图中顶点v为源点,使用Dijkstra算法求顶点v到图中其余各顶点的最短路径的基本思想如下: 使用集合S记录已求得最短路径的终点,初始时S={v}. 选择一条长度最小的最短路径,该路径的终点w属于V-S,将w并入S,并将该最短路径的长度记为Dw. 对于V-S中任一顶点是s,将源点到顶点

  • Python数据结构与算法之图的最短路径(Dijkstra算法)完整实例

    本文实例讲述了Python数据结构与算法之图的最短路径(Dijkstra算法).分享给大家供大家参考,具体如下: # coding:utf-8 # Dijkstra算法--通过边实现松弛 # 指定一个点到其他各顶点的路径--单源最短路径 # 初始化图参数 G = {1:{1:0, 2:1, 3:12}, 2:{2:0, 3:9, 4:3}, 3:{3:0, 5:5}, 4:{3:4, 4:0, 5:13, 6:15}, 5:{5:0, 6:4}, 6:{6:0}} # 每次找到离源点最近的一个顶

  • python编写的最短路径算法

    一心想学习算法,很少去真正静下心来去研究,前几天趁着周末去了解了最短路径的资料,用python写了一个最短路径算法.算法是基于带权无向图去寻找两个点之间的最短路径,数据存储用邻接矩阵记录.首先画出一幅无向图如下,标出各个节点之间的权值. 其中对应索引: A --> 0 B--> 1 C--> 2 D-->3 E--> 4 F--> 5 G--> 6 邻接矩阵表示无向图: 算法思想是通过Dijkstra算法结合自身想法实现的.大致思路是:从起始点开始,搜索周围的路径

  • Python 最短路径的几种求解方式

    目录 前言 前置知识 练习题 [单源最短路&迪杰斯特拉]畅通工程(续) [单源最短路 & spfa]最短路径 [多源最短路 & 弗洛伊德]牛牛聚会 前言 给出几个点的名称,在给出几个点的路径权重(简称路权)就可以计算一个地图中最短的路权是不是感觉很神奇.当然啦博主也觉得很神奇,因为博主比较笨嘛,如果只有几个点的图集的话还可以口算出来图中的最短路,如果有上千个点的话,博主的大脑就不够用了.所以呢咱们掌握最短路算法还是必须的,至少可以减少我们的脑力劳动嘛. 前置知识 图的话可以大致分为

  • Python 脚本的三种执行方式小结

    1.交互模式下执行 Python,这种模式下,无需创建脚本文件,直接在 Python解释器的交互模式下编写对应的 Python 语句即可. 1)打开交互模式的方式: Windows下: 在开始菜单找到"命令提示符",打开,就进入到命令行模式: 在命令行模式输入: python 即可进入 Python 的交互模式 Linux 下: 直接在终端输入 python,如果是按装了 python3 ,则根据自己建的软连接的名字进入对应版本的 Python 交互环境,例如我建立软连接使用的 pyt

  • Python字典 dict几种遍历方式

    目录 1.使用 for key in dict遍历字典 2.使用for key in dict.keys () 遍历字典的键 3.使用 for values in dict.values () 遍历字典的值 4.使用 for item in dict.items () 遍历字典的键值对 5.使用 for key,value in dict.items () 遍历字典的键值对 1.使用 for key in dict遍历字典 可以使用for key in dict遍历字典中所有的键 x = {'a

  • Python常见的几种数据加密方式

    目录 md5加密 解密 增加破解成本的方法 SHA1安全哈希算法 Base64伪加密 DES/AES AES和DES的区别 破解方法 RSA 非对称加密算法 使用流程和场景介绍 公钥私钥生成方式 前言: 常见的加密算法基本分为这几类: 线性散列算法(签名算法)MD5,sha1 对称性加密算法 AES DES 非对称性加密算法 RSA md5加密 MD5是一种被广泛使用的线性散列算法,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整的一致性.且MD5加密之后

  • Python线程的两种编程方式

    Python中如果要使用线程的话,python的lib中提供了两种方式.一种是函数式,一种是用类来包装的线程对象.举两个简单的例子希望起到抛砖引玉的作用,关于多线程编程的其他知识例如互斥.信号量.临界区等请参考python的文档及相关资料. 1.调用thread模块中的start_new_thread()函数来产生新的线程,请看代码: 复制代码 代码如下: ###        thread_example.py   import time  import thread  def timer(n

  • Python模块常用四种安装方式

    安装Python模块时大多还要依赖一些其他模块,可以利用自动化安装工具,会自动帮你解决依赖关系,自动帮你下载并安装所缺少的那些模块.这样我们可以有更多时间去用各种模块,而不是花很多时间在安装上. easy_insall的作用和perl中的cpan,ruby中的gem类似,都提供了在线一键安装模块的傻瓜方便方式,而pip是easy_install的改进版,提供更好的提示信息,删除package等功能.老版本的python中只有easy_install,没有pip. 现在pip是python官网上推

  • Python单例模式的四种创建方式实例解析

    单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在.当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场. 比如,某个服务器程序的配置信息存放在一个文件中,客户端通过一个 AppConfig 的类来读取配置文件的信息.如果在程序运行期间,有很多地方都需要使用配置文件的内容,也就是说,很多地方都需要创建 AppConfig 对象的实例,这就导致系统中存在多个 AppConfig 的实例对象,而这样会严重浪

  • python 进程的几种创建方式详解

    在新创建的子进程中,会把父进程的所有信息复制一份,它们之间的数据互不影响. 使用os.fork()创建 该方式只能用于Unix/Linux操作系统中,在windows不能用. import os # 注意,fork函数,只在Unix/Linux/Mac上运行,windows不可以 pid = os.fork() # 子进程永远返回0,而父进程返回子进程的ID. if pid == 0: print('子进程') else: print('父进程') 使用Process类类创建 multiproc

  • python线程的几种创建方式详解

    Python3 线程中常用的两个模块为: _thread threading(推荐使用) 使用Thread类创建 import threading from time import sleep,ctime def sing(): for i in range(3): print("正在唱歌...%d"%i) sleep(1) def dance(): for i in range(3): print("正在跳舞...%d"%i) sleep(1) if __name

  • Python selenium 三种等待方式详解(必会)

    很多人在群里问,这个下拉框定位不到.那个弹出框定位不到-各种定位不到,其实大多数情况下就是两种问题:1 有frame,2 没有加等待.殊不知,你的代码运行速度是什么量级的,而浏览器加载渲染速度又是什么量级的,就好比闪电侠和凹凸曼约好去打怪兽,然后闪电侠打完回来之后问凹凸曼你为啥还在穿鞋没出门?凹凸曼分分中内心一万只羊驼飞过,欺负哥速度慢,哥不跟你玩了,抛个异常撂挑子了. 那么怎么才能照顾到凹凸曼缓慢的加载速度呢?只有一个办法,那就是等喽.说到等,又有三种等法,且听博主一一道来: 1. 强制等待

随机推荐