最短路优化

最短路优化

写在前面

上次讲了最短路的基础,但是像最短路这种博大精深(坑特别深)的算法。。。是肯定有优化的啦。这一篇是给有最短路基础的人看的,假如没有嘛。。可以看看我以前写的最短路基础

SPFA

我把这个算法挪到这边来写了,原因有两个:第一个是我上次懒得写了。。
第二个是这个算法比较难,所以放在了优化这边一起写,而且它本身就是对贝尔曼福德的优化。
不说废话了,let's begin
spfa 算法可以适用于负边权的情况,是 bellman-ford 的队列优化。
假设存在 G=<V,E>,dis[i]记录 V0 到 i 的最短距离,pre[i]记录从 V0 到 i 路径 上 i 的前面的一个顶点;
step1.将所有顶点对之间距离初始化为无穷大(dis[i][j]=无穷大),pre[i]=i, vis[i]=0,将源点入队;
step2.读取队头顶点 now,并将队头顶点 now 出队(记得消除标记),将与点 now 相连的所有点 next 进行松弛操作(还记得吗,上一篇讲过),更新 dis[next],另外,如果点 next 没有 在队列中,那么要将点 next 入队(记得标记),如果已经在队列中了,那么就不 用入队(如果某个顶点入队超过 V 次,则说明图中有负环,直接跳出);
step3.重复 step2,直到队空为止就完成了单源最短路的求解。
这是主要思路。
下面有个图解(无耻的转自某博客)😅

spfa_1.jpg
spfa_2.jpg

其实它和bfs非常类似(bfs在我创建的专题里有人讲过)。只是bfs中的一个点出了队列就不会再回来了,而最段路中由于有环的存在,导致了一个点可能进入队列多次。
spfa函数附上


spfa函数.png

下面是洛谷题解的一个,感觉注释写的挺详细,也附上。

void spfa()
{
  queue<int> q; //spfa用队列,这里用了STL的标准队列
  for(int i=1; i<=n; i++) 
  {
    dis[i]=inf; //带权图初始化
    vis[i]=0; //记录点i是否在队列中,同dijkstra算法中的visited数组
  }
  q.push(s); dis[s]=0; vis[s]=1; //第一个顶点入队,进行标记
  while(!q.empty())
  {
    int u=q.front(); //取出队首
    q.pop(); vis[u]=0; //出队标记
    for(int i=head[u]; i; i=edge[i].next) //邻接表遍历,不多解释了(也可用vector代替)
    {
      int v=edge[i].to; 
      if(dis[v]>dis[u]+edge[i].dis) //如果有最短路就更改
      {
        dis[v]=dis[u]+edge[i].dis;
        if(vis[v]==0) //未入队则入队
        {
          vis[v]=1; //标记入队
          q.push(v);
        }
      }
    }
  }
}

spfa这个算法非常好用(功能强大,效率高😎)
基本上单源最短路的题都可以用spfa,墙裂推荐

狄杰斯特拉(堆优化)

真不知道为什么会有人把它念成迪克特斯拉😂
(需要有堆的基础)
思路:在寻找周围最小点的时候,用最小堆,可以用 O(log n)的时间找出最小的可到达点。
是不是感觉很蛋疼。。但是很秀🤔
最小堆:最小堆,是一种经过排序的完全二叉树,其中任一非终端节点的数据值均不大于其左子节点和右子节点的值。
最小堆后面可能会说,但是这里嘛。。就很不负责任的推荐一个别人的博客:别人家的最小堆
别嫌弃呀。。
堆优化的主要思想就是使用一个优先队列(就是每次弹出的元素一定是整个队列中最小的元素)来代替最近距离的查找,用邻接表代替邻接矩阵,这样可以大幅度节约时间。
在这里有几个坑要先填一下:
首先来讲,优先队列的数据类型应该是怎样的呢?
我们知道优先队列应该用于快速寻找距离最近的点。由于优先队列只是将最小的那个元素排在前面,因此我们应该定义一种数据类型,使得它包含该节点的编号以及该节点当前与起点的距离。
辣么。。我们应该在什么时候对队列进行操作呢?
队列操作的地方,首先就是搜索刚开始,要为起点赋初始值,此时必须将起点加入优先队列中。该队列元素的节点编号为起点的编号,该节点当前与起点的距离为0。
那么如果一个节点到起点的最短距离通过其他的运算流程发生了变化,那么如何处理队列中的那个已经存入的元素?
事实上,你不需要理会队列中的元素(暴力无视),而是再存入一个就行了。因为如果要发生变化,只能将节点与起点之间的距离变得更小,而优先队列恰好是先让最小的那个弹出。
因此,轮到某一个队列元素弹出的时候,如果有多个元素的节点编号相同,那么被弹出的一定是节点编号最小的一个。等到后面再遇到这个节点编号的时候,我们只需要将它忽略掉就行了。
是不是感觉hin棒?😬
最小堆优化的迪杰有一个模版题:

例:网吧
【问题背景】
绵阳中学以人数众多而闻名。三个年级共有 10000 多人,学生多了附近的 网吧也多。Mzoiers 都热衷于 Dota,可学校的机子配置相当差(评测服务器除外), 根本不能玩 Dota,那就只有去网吧。星期天到星期五都是晚上 10:20 才下晚自 习,几乎没时间玩。
然而星期六下午放假是绝好的时间,但是学校人多啊,一放学去网吧的人就 开始狂奔,竞争之激烈,抢到机子的难度非常之大。往往在我们到达网吧之前都 坐满了。
学校到网吧的路是错综复杂的,以致于到一个自己想去的网吧都有非常多的 路线可以选择,而路线的长度又不相同,这样就决定了要花费的时间,因此想要 尽快到达,选择一条最佳的线路是很有必要的。
【问题描述】
为了简化问题,我们把学校与周边的网吧看做图中的顶点,学校与网吧,网 吧与网吧之间的路线看做边,每个边都有一个权,表示我们走完这条路的时间, 由于放学人流量大,如果反向走会有危险,因此这是一个有向图。
我的的学校在 S 点,想要去的网吧在 T 点。你的任务就是选择一条最佳路线, 使得从学校到目的地网吧的时间最短,你只需要输出最短到达时间即可。 【输入文件】
netbar.in 中共有 M+2 行数据
第一行两个整数 N,M,表示点数和边数。
然后 M 行每行 3 个正整数(u,v,t),表示有一条可由 u 到 v 耗时为 t 的边。 最后一行两个正整数 S、T。
【输出文件】
netbar.out 中,只有一行,一个整数表示最短时间。如果 S、T 之间不存在通 路则输出“No Solution!”(双引号不输出,“!”为西文标点)。
【输入样例】
44 123 2 4 10 135 345 14
【输出样例】
10
【数据规模】
对于 30%的数据保证有 1<N<=1000,1<=M<=1000; 对于全部的数据保证有 1<N<=10000,1<=M<=100000。

注明:我不是绵中的(也不打算去),我和绵中也没有什么利益关系。题目不是我出的,如果觉得它对绵中不怀好意。。。也别找我
下面附上标程:


迪杰1.jpg

迪杰2.jpg
迪杰3.png
迪杰 4.jpg

迪杰优化一般情况下用的不是很多,但是在某些特殊场合是可以用的。也看得出来优化不是很复杂,比较好理解。对迪杰情有独钟的同学可以记一下。

ending

最短路这个博大精深的算法也算是图论的核心,所以。。学好最短路很重要。
看在我这么用心的份上滋瓷一下呗。。
不要问我为什么这篇的程序都是图片。。
其实。。介绍一个方法(也不知道算不算了)。在遇到最段路的题的时候,windows系统的同学可以打开画图,把样例画成一个图,在推一遍,可以看得很直观,免得对着几个数字空想,很抽象。
(老师附体)(苦口婆心)以上内容可能有点难度,建议多看几遍,多想几下,最好能推一遍。。。
(在你嫌弃我之前跑掉)😝

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,287评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,346评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,277评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,132评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,147评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,106评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,019评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,862评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,301评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,521评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,682评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,405评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,996评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,651评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,803评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,674评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,563评论 2 352