Travel [BFS]

话说这道题并没有找到提交的地方…就不写代码了[滑稽]

题目描述

给定一张n 个点的完全图,边都是无向的。

一共有n(n−1)/2 条边,其中有m 条边的边权是a,剩下的边边权都是b。

求1 到n 的最短路。

数据范围

2 ≤ n ≤ 100000; 0 ≤ m ≤ 500000

题解

一 初步分析

这是一张完全图,也就是说任意两点之间必有一条路相连。

如果Len[1>n]==a,那么最短路里面肯定不能再包含a,即Lena

同理可得Len[1>n]==b的情况。

所以最短路一定只包含ab

现在只用把含a和含b的边单独提出来跑最短路,并在两个答案里面取最小值即可。

二 如何跑最短路

对于第一张图(边权全部为a的图),边数并不是很多,O(m)时间复杂度内就可以BFS跑完。(dijkstra的时间复杂度是(n+m)log n

对于第二张图(边权全部为b的图),显然不能够直接用BFS跑。

我们考虑BFS的执行过程:BFS是把队列中的每一个点延伸出去的边依次讨论,并把没在队列中的点加入队中,很多时间浪费在了没有用的边上。实际上,这么多条边里面最多只有n条边是有用的,也就是说,每个点只需要入队一次。如果避免了重复进队的点和无用的边,就可以快速找出最短路。

现在的任务是,精确地找出连向最短路的点

由分析可得,边权为b的边(简称b边)最多会被分为m个部分(考虑从一个点辐射状发出的边中,有ma边,剩余的全是b边;其余情况同样如此)(当有a边相邻时,b边会被分为<m个部分;这并没有什么影响)

Travel [BFS]

我们给每条边编号(没有特别的顺序)。

设一个b边的区间为[L,R]fa[i]表示编号>=i,且不在队列中的最小编号。初始时fa[i]=i,类似于并查集。注意:这与并查集中fa[i]的定义有所不同。

按照边的编号顺序,对每一个区间进行如下操作:

  1. int x=getfa(L);

  2. while(x<=R){x入队; 进行最短路的操作; fa[x]=x+1; x=getfa(x+1);}

    I. fa[x]=x+1是因为x+1尚未入队。

    II. 最后一句表示的是x往后跳。精确地找出在最短路上的点。

然后我们就可以愉快地得出第二张图的最短路了。

最后比较两张图的答案,输出最小值。

相关文章: