最短路径学习总结

本周学习了最短路径问题,与上周的最小生成树不一样的是,最小生成树是以无向带权图为基准,而最短路径是以加权有向图为基准。

目录

1.SPFA算法:

2.Dijkstra算法

3.Floyd算法

二.例题展示:

《1》P1576 最小花费

《2》P1629 邮递员送信

《3》P1821 [USACO07FEB] Cow Party S


在最短路径问题中,这三个算法穿插其中:

1.SPFA算法:

SPFA算法
SPFA是一种用队列优化的B-F算法,看上去和BFS很像,B-F效率较低就不介绍了,还有一种用DFS优化B-F的SPFA但是往往这种方法比平时更加劣化没有队列优化的好用,平时用SPFA就够用了。可以解决负边问题,可以判断负环是否存在。在稀疏图中,采用类似邻接链表储存比较节省空间。

参数解释
node结构体:用来储存边,数组下标代表边起点,结构体中的v,代表边的终点,weight/w代表权值
dis数组:储存起点到各个点的距离,dis[i]就是起点到i点的距离。
vis数组:标记点是否访问过
INF:宏定义的最大值路不通

算法思想
初始时,只有把起点放入队列中。遍历与起点相连的边,如果可以松弛就更新距离dis[],然后判断如果这个点没有在队列中就入队标记。出队队首,取消标记,循环2-3步,直至队为空。所有能更新的点都更新完毕,dis[]数组中的距离就是,起点到其他点的最短距离。

2.Dijkstra算法

算法思路
(1)维护一个集合,初始状态为一个起点,这个集合表示里面的点的dist [ i ]  已经是最短路径了。
(2)遍历所有点,取一个集合外的离集合最近的点并入集合,并且用这个点去更新外点到集合的距离
(3)循环n-1次前两步。(实际编程中可以把起点的dist值置为0,其他的为inf,然后直接从空集合开始循环n次即可,看大家编程习惯了)

3.Floyd算法

其实就是利用动态规划:
dp[ i ] [ j ] = min(dp[ i ] [ j ] , dp[ i ] [ k ] + dp[ k ] [ j ] ) . dp[i][j] = min(dp[i][j],dp[i][k]+dp[k][j]).
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]).

我们要做的是遍历所有中间点k,然后内嵌ij遍历去做到对所有的ij距离的极小化。

二.例题展示:

《1》P1576 最小花费

https://www.luogu.com.cn/problem/P1576

题目描述

在n个人中,某些人的银行账号之间可以互相转账。这些人之间转账的手续费各不相同。给定这些人之间转账时需要从转账金额里扣除百分之几的手续费,请问A最少需要多少钱使得转账后B收到100元。

输入格式

第一行输入两个正整数n,m,分别表示总人数和可以互相转账的人的对数。

以下m行每行输入三个正整数x,y,z,表示标号为x的人和标号为y的人之间互相转账需要扣除z%的手续费 (z<100)。

最后一行输入两个正整数A,B。数据保证A与B之间可以直接或间接地转账。

输出格式

输出A使得B到账100元最少需要的总费用。精确到小数点后8位。

题解:

这道题本质上就是一道最短路的变种,转账时候收取1%手续费可以理解为这条边边权为0.99,而且边权是相乘而不是相加

为了更好理解,这里解释一下样例:要求从1到3,如果从1到2,手续费1%,那么钱数就乘0.99;2到3再乘0.98,这样总倍数是0.9702,优于直接1给3的0.97倍,所以答案是100/0.97。

注意不是转化率,是到账100元最少需要的总费用!!!

《2》P1629 邮递员送信

https://www.luogu.com.cn/problem/P1629

题目描述

有一个邮递员要送东西,邮局在节点 11。他总共要送 n-1n−1 样东西,其目的地分别是节点 22 到节点 nn。由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有 mm 条道路。这个邮递员每次只能带一样东西,并且运送每件物品过后必须返回邮局。求送完这 n-1n−1 样东西并且最终回到邮局最少需要的时间。

输入格式

第一行包括两个整数,nn 和 mm,表示城市的节点数量和道路数量。

第二行到第 (m+1)(m+1) 行,每行三个整数,u,v,wu,v,w,表示从 uu 到 vv 有一条通过时间为 ww 的道路。

输出格式

输出仅一行,包含一个整数,为最少需要的时间。

题解:

求点1到其余所有点的最短路很简单,就是Dijkstra的板子。那么所有点到点1的最短路怎么求呢?取反向图,再用Dijkstra的板子求出反向图中点1到其余所有点的最短路。之后求和就行了。

《3》P1821 [USACO07FEB] Cow Party S

https://www.luogu.com.cn/problem/P1821

题目描述

寒假到了,nn 头牛都要去参加一场在编号为 xx 的牛的农场举行的派对,农场之间有 mm 条有向路,每条路都有一定的长度。

每头牛参加完派对后都必须回家,无论是去参加派对还是回家,每头牛都会选择最短路径,求这 nn 头牛的最短路径(一个来回)中最长的一条路径长度。

输入格式

第一行有三个整数,分别表示牛的数量 nn,道路数 mm 和派对农场编号 xx。
接下来 mm 行,每行三个整数 u, v, wu,v,w,表示存在一条由 uu 通向 vv 的长度为 ww 的道路。

输出格式

输出一行一个整数表示答案。

题解:

从每个点做一次spfa,记录下每个点到x点的距离(即奶牛们去的距离),然后再以x点为起点做一次spfa,在记录从x点到每个点的距离(即奶牛们回来的距离)。

三.总结:

这周的内容我感觉比并查集要简单很多,很多都是模板题,感觉万变不离其宗,但是反向建图却给我提供了很好的思路,让我感觉耳目一新。下周要看贪心了,虽然这部分我提前学过,但是好像这一部分的博客会比较难,还是得好好上心才是。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值