图论1 最短路问题的建图方式

(代码部分待补)

核心:题意转化,建立抽象模型

注意数据范围选择对应模版:

稠密图点少边多(m≈n^2就可以认为是稠密),适合朴素dij或prim

稀疏图点多边少,适合堆优化dij

各个算法简单总结

1.Spfa O(n~mn)

循环队列写法:(也是实际应用中的模版)

因为点的反复入队,无法确定队列长度,容易爆内存

因此使用循环队列,改动如下:

①初始化时hh=0,tt=0;

②取队首弹出后if(hh==n) hh=0;

③定点入队后if(tt==n) tt=0;

2.Dijkstra(堆优化) O(mlogn)

类似bfs,两者区别是:

①bfs最先搜到的点一定是最近的,所以入队前判重,每一个状态只会被更新一次。

②堆优化版dij每次更新堆都要重新排序,即每一个点可能被访问和更新多次,只有在出队的时候才可以保证当前的dis[ver]是最小的,所以在出队判重。

补充复习:

对于A*算法来说出队的时候不用判重,终点第k次出队的时候那么求解的是起点到终点的第k短路。

3.Bellmanford O(mn)

只用来求边数限制的最短路

(因为每一条边都会考虑,spfa则不是)

注意需要备份,松弛操作:dist[x.b] = min(dist[x.b], backup[x.a]+x.w);

实战训练

1.信使

题意:求从起点送到所有的点这整个过程最短时间

转化:单源最短路(最短)的最大值(整个过程)

  1. 黄油

题意:选一个点,满足所有的点到他的距离之和最小

转化:求所有点到其他全部点的最短路

  1. 花费

题意:a给b转账,要想让b得到100钱,a最少准备多少钱

转化:(n~1e3,m~1e5)

设刚开始的钱是x,每两个人之间的交易率wi,则100=x∗(w1*w2*..)

x最小→w1∗w2∗w3..w1∗w2∗w3..最大

在这道题目中,我们可以用朴素dij(邻接矩阵)求最短路,数学证明过程:

我们以前的最短路求的都是和的最小值,那么就要:

①积化和——取对数

→log(w1)+log(w2)+...最大

②求最大转求最小

因为w<=1,所以log(w)<=0

那么将每个数取相反数,保证没有负权路(否则没有单调的“传递性”),就是求最短路了

注意初始化起点的时候w为1,不是0,w不是普通求最短路的dist

补充:最短路问题什么时候可以求乘积?

①0<w<=1:dij ②w>0:spfa

  1. 乘车

题意:已知公交路线,求从起点到终点的最少换乘次数

转化:已知边权均为1的有向图,求最短路-1(换乘!不是乘车!),直接bfs即可

注意特判,如果无法到达要输出0

  1. 聘礼

题意:买东西有两种方式,付所有的钱/交一个东西+付部分钱。已知一个部落,并且等级差距过大的人之间不会进行交易,求买到最终物品的最少钱

转化:每个人为顶点,满足等级差距+拥有可以抵押的物品则连边,边权为付的钱

但是要是选第一种方式,就无法按照这种方式建边了。那么就凭空出现一个人,它有一个价值为0的万能物品可以抵押所有人的条件→虚拟源点和所有已知的点连边

实现代码时注意取值范围

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值