Luogu P3547 [POI2013] CEN-Price List 题解 BFS 广度优先搜索

题目链接:Luogu P3547 [POI2013] CEN-Price List

题目描述:

给定一张边权均为a的无向图,现在将所有两点之间最短路为2a的点之间增加一条长度为b的无向边,问到给定点s的单元最短路。

题解:

对于一个点us的最短路只有三种情况:

  1. 经过的边边权均为a
  2. 经过的边边权均为b
  3. 经过的边边权ab均有。

我们只需要求出上面三种情况的最短路取最小值即可。

对于情况一只需要进行一次BFS即可求出。

对于情况二我们同样可以通过一次BFS求出:

  1. 我们首先建立两张与原图一样的图,我们将两张图的边权全部记作1这样只需在最后的时候乘以a或者b即可,将这两张图记为gnewG
  2. 对于本轮BFS的结点u,标记其在g中的相邻结点v已访问;
  3. 通过g遍历与u相邻的结点v,通过newG遍历与v相邻的结点w;若w已经被标记,则说明uw之间的最短路为1,此时两者之间不存在边长为b的边,不能更新dis;若w并没有被标记,说明uw之间的最短路距离为2,此时存在边长为b的边,所以进行更新dis[w] = dis[u] + 1,并将w入队,删除vw的边;
  4. 通过g遍历与u相邻的结点v,标记其为未访问。

上述的过程需要删除vw的边,可以通过前向星实现(建立双向链表)。该算法与三元环计数类似,时间复杂度为 O ( ( n + m ) m ) O((n + m) \sqrt m) O((n+m)m )。能够删除的原因是:根据BFS可以知道先遍历的点的dis一定小于后遍历的点的距离,如果之前通过vw的这条边更新过,后续通过这条边的距离一定会更大,因此不需要重复遍历。

对于情况三我们可以发现最多只会经过一条边权为a的边。这是因为,如果我们经过了边权为b的边,那么说明b<2a否则不会更优,那么既然这样,每有两条边权为a的边,则可以进行走一次边权为b的边进行优化,最会只可能剩下一条或者零条边权为a的边,如果将原图的边权改为1求得一次的单元最短路的结果记为dis[u]us的最短路),则情况三为: ⌊ d i s [ u ] 2 ⌋ ∗ b + d i s [ u ] m o d 2 ∗ a \lfloor\frac {dis[u]} 2\rfloor * b + dis[u]\ mod\ 2 * a ⌊2dis[u]⌋∗b+dis[u] mod 2∗a。

代码:LuoguP3547

相关推荐
代码雕刻家1 分钟前
课设实验-数据结构-单链表-文教文化用品品牌
c语言·开发语言·数据结构
sp_fyf_202417 分钟前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-02
人工智能·神经网络·算法·计算机视觉·语言模型·自然语言处理·数据挖掘
小字节,大梦想1 小时前
【C++】二叉搜索树
数据结构·c++
我是哈哈hh2 小时前
专题十_穷举vs暴搜vs深搜vs回溯vs剪枝_二叉树的深度优先搜索_算法专题详细总结
服务器·数据结构·c++·算法·机器学习·深度优先·剪枝
Tisfy2 小时前
LeetCode 2187.完成旅途的最少时间:二分查找
算法·leetcode·二分查找·题解·二分
Mephisto.java2 小时前
【力扣 | SQL题 | 每日四题】力扣2082, 2084, 2072, 2112, 180
sql·算法·leetcode
robin_suli2 小时前
滑动窗口->dd爱框框
算法
丶Darling.2 小时前
LeetCode Hot100 | Day1 | 二叉树:二叉树的直径
数据结构·c++·学习·算法·leetcode·二叉树
labuladuo5202 小时前
Codeforces Round 977 (Div. 2) C2 Adjust The Presentation (Hard Version)(思维,set)
数据结构·c++·算法
Indigo_code3 小时前
【数据结构】【链表代码】合并有序链表
数据结构·windows·链表