问题描述

给定一个n个点m条边的无向无权重的图,找出所有点对之间的近似最短距离。

思路

最简单的方法就是从每个点开始跑BFS了。BFS的时间复杂度是All-Pair Almost Shortest Path(APASP)_最短距离的,那么总的时间复杂度就是All-Pair Almost Shortest Path(APASP)_算法_02的。但是如果是稠密图,那All-Pair Almost Shortest Path(APASP)_算法_03,总的时间复杂度就是All-Pair Almost Shortest Path(APASP)_最短距离_04了。所以思路就是生成边数比较少的子图,然后加上一些构造出来的边来弥补那些被删掉的边造成的影响,再对得到的图跑最短路,来近似给出完整的图的结果。

随机选点

生成边数比较少的子图时,常用的方法是在图中随机选一些点,使得度数All-Pair Almost Shortest Path(APASP)_最短距离_05的点大概率与某个选出来的点相邻。

假设每个点被选中的概率为All-Pair Almost Shortest Path(APASP)_时间复杂度_06,那么一个度数为d的点的邻居中,有一个点被选中的概率就是All-Pair Almost Shortest Path(APASP)_时间复杂度_07。可以证明只要随机选出All-Pair Almost Shortest Path(APASP)_最短距离_08个点即可(我不会证明)。其中All-Pair Almost Shortest Path(APASP)_子图_09表示All-Pair Almost Shortest Path(APASP)_算法_10,其中All-Pair Almost Shortest Path(APASP)_子图_11为常数。

两层图:

All-Pair Almost Shortest Path(APASP)_最短距离_12为度数All-Pair Almost Shortest Path(APASP)_时间复杂度_13的点的集合。我们随机选出All-Pair Almost Shortest Path(APASP)_子图_14个点All-Pair Almost Shortest Path(APASP)_最短距离_15,使得所有All-Pair Almost Shortest Path(APASP)_最短距离_12中的点高概率与All-Pair Almost Shortest Path(APASP)_最短距离_15中的某个点相邻。

All-Pair Almost Shortest Path(APASP)_最短距离_18为满足All-Pair Almost Shortest Path(APASP)_时间复杂度_19All-Pair Almost Shortest Path(APASP)_最短距离_20的边(u, v)组成的边集。这样All-Pair Almost Shortest Path(APASP)_最短距离_18就相当于我们生成的边数比较少的子图了。由于其中的每条边的两个端点中,其中一方的度数必小于All-Pair Almost Shortest Path(APASP)_时间复杂度_22,也就是说,我们遍历所有的度数All-Pair Almost Shortest Path(APASP)_时间复杂度_22的点发出的边,即可遍历到所有的边,然后这样的点的个数最多是n,所以总的边数All-Pair Almost Shortest Path(APASP)_子图_24

我们在这个子图里对每个点跑BFS的话,对于点对(u, v),假如u和v以及它们的最短路径上所有的点的度数都小于All-Pair Almost Shortest Path(APASP)_时间复杂度_22,那么就可以求出来。但是如果路径上存在某个度数All-Pair Almost Shortest Path(APASP)_时间复杂度_13的点w(有可能是u或v本身),使得最短路径上某条边可能不在All-Pair Almost Shortest Path(APASP)_最短距离_18里,我们怎么估计出原图中u和v的最短路呢?

注意到w高概率与All-Pair Almost Shortest Path(APASP)_最短距离_15中的某个点w’相邻,所以考虑用w’为跳板,求出u到w’和w’到v的最短距离。记原图中u和v之间的最短距离为All-Pair Almost Shortest Path(APASP)_最短距离_29,那么All-Pair Almost Shortest Path(APASP)_最短距离_30All-Pair Almost Shortest Path(APASP)_时间复杂度_31,所以All-Pair Almost Shortest Path(APASP)_算法_32,即误差最大为2。

所以我们先在原图中对每个All-Pair Almost Shortest Path(APASP)_最短距离_15中的点跑一遍BFS,拿到All-Pair Almost Shortest Path(APASP)_时间复杂度_34里每个点对的最短距离,这个时间复杂度为All-Pair Almost Shortest Path(APASP)_最短距离_35。然后往All-Pair Almost Shortest Path(APASP)_子图_36中加入权重为All-Pair Almost Shortest Path(APASP)_最短距离_29的从u到v的边,其中All-Pair Almost Shortest Path(APASP)_子图_38All-Pair Almost Shortest Path(APASP)_算法_39,加入的这些边的集合记为All-Pair Almost Shortest Path(APASP)_算法_40,得到的图则为All-Pair Almost Shortest Path(APASP)_子图_41,其边数仍然为All-Pair Almost Shortest Path(APASP)_时间复杂度_42。然后对得到的图的每个点跑dijkstra,复杂度All-Pair Almost Shortest Path(APASP)_子图_43,就能得到误差最多为2的每个点对之间的最短路长度了。总的复杂度就是All-Pair Almost Shortest Path(APASP)_子图_43

一些想法:上面的描述中,使用All-Pair Almost Shortest Path(APASP)_最短距离_18时,我其实加上了u和v的度数都小于All-Pair Almost Shortest Path(APASP)_时间复杂度_22的假设,这样其实All-Pair Almost Shortest Path(APASP)_最短距离_18里只保留两个端点的度数都小于All-Pair Almost Shortest Path(APASP)_时间复杂度_22的边就好了,然而这样并不能减少All-Pair Almost Shortest Path(APASP)_最短距离_18里的边数,而且这样的话,对于相邻的一个度数小于All-Pair Almost Shortest Path(APASP)_时间复杂度_22,一个度数All-Pair Almost Shortest Path(APASP)_时间复杂度_13的点,本来可以都在All-Pair Almost Shortest Path(APASP)_最短距离_18里求出精确值,但是却非得以All-Pair Almost Shortest Path(APASP)_最短距离_15中的点为跳板,导致可能出现误差。

三层图:

三层图的结构即一个原图,一个2/3的子图,一个1/3的子图,而且由于同样只用了一个中继点,最大的误差仍然为2。

All-Pair Almost Shortest Path(APASP)_最短距离_12为度数All-Pair Almost Shortest Path(APASP)_子图_55的点构成的点集。
All-Pair Almost Shortest Path(APASP)_算法_56为度数All-Pair Almost Shortest Path(APASP)_算法_57的点构成的点集。
All-Pair Almost Shortest Path(APASP)_最短距离_15为随机选出的All-Pair Almost Shortest Path(APASP)_时间复杂度_59个点,这样All-Pair Almost Shortest Path(APASP)_最短距离_12里每个点都大概率与一个All-Pair Almost Shortest Path(APASP)_最短距离_15中的点相邻。
All-Pair Almost Shortest Path(APASP)_算法_62为随机选出的All-Pair Almost Shortest Path(APASP)_最短距离_63个点,这样All-Pair Almost Shortest Path(APASP)_算法_56里每个点都大概率与一个All-Pair Almost Shortest Path(APASP)_算法_62中的点相邻。
All-Pair Almost Shortest Path(APASP)_最短距离_18为满足All-Pair Almost Shortest Path(APASP)_时间复杂度_19All-Pair Almost Shortest Path(APASP)_最短距离_20的边(u, v)构成的边集。
All-Pair Almost Shortest Path(APASP)_算法_69为满足All-Pair Almost Shortest Path(APASP)_最短距离_70All-Pair Almost Shortest Path(APASP)_时间复杂度_71的边(u, v)构成的边集。
All-Pair Almost Shortest Path(APASP)_最短距离_72为将每个All-Pair Almost Shortest Path(APASP)_算法_56中的点连接到一个All-Pair Almost Shortest Path(APASP)_算法_62中的点的边构成的集合。注意,每个All-Pair Almost Shortest Path(APASP)_算法_56中的点对应All-Pair Almost Shortest Path(APASP)_最短距离_72中的一条边,不然最后的复杂度就不对了。

我们先从All-Pair Almost Shortest Path(APASP)_算法_69开始考虑。如果我们直接在All-Pair Almost Shortest Path(APASP)_算法_69上对每个点做BFS,那假如点对(u, v)之间的最短路上所有点(包括u和v)都不属于All-Pair Almost Shortest Path(APASP)_算法_56,那么求出来的就是精确值。但是,如果路径上存在属于All-Pair Almost Shortest Path(APASP)_算法_56的点,那么就可能有边不在All-Pair Almost Shortest Path(APASP)_算法_69中。这时我们考虑引入中继点来弥补。假设w是最后一个属于All-Pair Almost Shortest Path(APASP)_算法_56的点(可能是v),那么在All-Pair Almost Shortest Path(APASP)_算法_62中就大概率有一个点w’与w相邻。显然w到v的最短路径上的边都在All-Pair Almost Shortest Path(APASP)_算法_69里,因此w’到v在All-Pair Almost Shortest Path(APASP)_算法_85上的最短路径长度最多比w到v的最短路径大1。现在问题转化为如何得到u到w’的无误差最短路长度,即每个All-Pair Almost Shortest Path(APASP)_算法_86中的点对的最短路径长度。

最简单的方法当然是直接在原图上对每个All-Pair Almost Shortest Path(APASP)_算法_62中的点跑BFS,但是这样的话复杂度太高了。

其实对于三层的图,有一个很美妙的性质:如果u到v的最短路上存在属于All-Pair Almost Shortest Path(APASP)_最短距离_12的点w,那么大概率存在一个All-Pair Almost Shortest Path(APASP)_最短距离_15中的点w’,使得w’与w相邻,然后只要我们先对每个All-Pair Almost Shortest Path(APASP)_最短距离_15中的点跑BFS,得到边集All-Pair Almost Shortest Path(APASP)_算法_40,然后只要图中加入这个边集,就能得到这种情况下误差最大为2的最短路长度,跟两层图同理。

这样,我们就只需要求解对于All-Pair Almost Shortest Path(APASP)_算法_86中的点对,两点之间的最短路径上所有点都All-Pair Almost Shortest Path(APASP)_算法_93时,最短路径是多少了。我们发现,这些边恰好都在All-Pair Almost Shortest Path(APASP)_最短距离_18中。所以我们在All-Pair Almost Shortest Path(APASP)_最短距离_18里对每个All-Pair Almost Shortest Path(APASP)_算法_62中的点跑BFS,得到All-Pair Almost Shortest Path(APASP)_子图_97。算起点为u的最短路径时,只需要把All-Pair Almost Shortest Path(APASP)_时间复杂度_98加入到图中即可,不然复杂度不对。

所以总的流程如下:

  1. 在原图对每个All-Pair Almost Shortest Path(APASP)_最短距离_99中的点跑BFS,得到边集All-Pair Almost Shortest Path(APASP)_算法_100,复杂度All-Pair Almost Shortest Path(APASP)_子图_101
  2. All-Pair Almost Shortest Path(APASP)_最短距离_102中对每个All-Pair Almost Shortest Path(APASP)_时间复杂度_103中的点跑BFS,得到边集All-Pair Almost Shortest Path(APASP)_算法_104,由于All-Pair Almost Shortest Path(APASP)_算法_105All-Pair Almost Shortest Path(APASP)_子图_106,所以复杂度All-Pair Almost Shortest Path(APASP)_子图_101
  3. 对每个点u,在All-Pair Almost Shortest Path(APASP)_算法_108中对每个点跑dijkstra。由于All-Pair Almost Shortest Path(APASP)_子图_109All-Pair Almost Shortest Path(APASP)_子图_110All-Pair Almost Shortest Path(APASP)_子图_111All-Pair Almost Shortest Path(APASP)_时间复杂度_112,所以总的边数是All-Pair Almost Shortest Path(APASP)_最短距离_113,复杂度是All-Pair Almost Shortest Path(APASP)_子图_101

所以最终的复杂度就是All-Pair Almost Shortest Path(APASP)_算法_115。一切都刚刚好,太妙了orz


分为k层,共k-1个中继节点,所以误差最大为2(k-1)。

All-Pair Almost Shortest Path(APASP)_时间复杂度_116为度数All-Pair Almost Shortest Path(APASP)_最短距离_117的点构成的集合。All-Pair Almost Shortest Path(APASP)_算法_118就是所有点的集合All-Pair Almost Shortest Path(APASP)_最短距离_119
All-Pair Almost Shortest Path(APASP)_最短距离_120为随机选出的All-Pair Almost Shortest Path(APASP)_最短距离_121个点,这样每个All-Pair Almost Shortest Path(APASP)_时间复杂度_116中的点都大概率跟某个All-Pair Almost Shortest Path(APASP)_最短距离_120中的点相邻。All-Pair Almost Shortest Path(APASP)_子图_124
All-Pair Almost Shortest Path(APASP)_子图_125为满足All-Pair Almost Shortest Path(APASP)_算法_126All-Pair Almost Shortest Path(APASP)_子图_127的边(u, v)构成的边集。
All-Pair Almost Shortest Path(APASP)_最短距离_128为将每个All-Pair Almost Shortest Path(APASP)_时间复杂度_116中的点连接到一个All-Pair Almost Shortest Path(APASP)_最短距离_120中的点的边构成的集合。

思路:从i = 1到k,每次求出All-Pair Almost Shortest Path(APASP)_时间复杂度_131中每个点对的误差为2(i-1)的最短路径长度,算完到i = k后,就把All-Pair Almost Shortest Path(APASP)_最短距离_132中每个点对的误差为2(k-1)的最短路径长度给算出来了,这就是我们要求的。

i = 1的情况,直接在原图上(即All-Pair Almost Shortest Path(APASP)_子图_36)对每个All-Pair Almost Shortest Path(APASP)_最短距离_15中的点做BFS即可。

i > 1的情况,假如我们在All-Pair Almost Shortest Path(APASP)_算法_135中对每个All-Pair Almost Shortest Path(APASP)_最短距离_120中的点跑BFS,那么对于点对(u, v),假如最短路径上所有点都All-Pair Almost Shortest Path(APASP)_算法_137,那么求出的就是精确值,否则,设w为最后一个属于All-Pair Almost Shortest Path(APASP)_最短距离_138的点,那么大概率存在一个All-Pair Almost Shortest Path(APASP)_时间复杂度_139,使得w’与w相邻。从w’到v的最短路径长度可以在All-Pair Almost Shortest Path(APASP)_时间复杂度_140中求出来。然后我们又已知All-Pair Almost Shortest Path(APASP)_算法_141中每个点对的误差为2(i-2)的最短路径长度,假设u到All-Pair Almost Shortest Path(APASP)_最短距离_142的最短路径长度构成的边集是All-Pair Almost Shortest Path(APASP)_时间复杂度_143,那么对每个All-Pair Almost Shortest Path(APASP)_子图_144,以u为起点,在All-Pair Almost Shortest Path(APASP)_最短距离_145里跑dijkstra即可得到误差最多为2(i-1)的最短路径长度。

因为All-Pair Almost Shortest Path(APASP)_时间复杂度_146All-Pair Almost Shortest Path(APASP)_子图_147All-Pair Almost Shortest Path(APASP)_算法_148,所以跑dijkstra的总边数为All-Pair Almost Shortest Path(APASP)_最短距离_149,由于All-Pair Almost Shortest Path(APASP)_算法_150,所以复杂度为All-Pair Almost Shortest Path(APASP)_时间复杂度_151。跑k次,总复杂度All-Pair Almost Shortest Path(APASP)_算法_152

我的想法:可不可以把三层图里直接把最顶层消掉的方法泛化到这里呢?少一个中继点就可以提高一些精度。

对稀疏图进行优化

注意到,前面的算法在分层的时候只用到了n,但是如果是稀疏图的话,其实高度数的节点是很少的,那其实很多层其实是白分了。所以对稀疏图的优化的思路就是在分层的时候,我们同时用到n和m。论文里给出的分层方法是把原先的All-Pair Almost Shortest Path(APASP)_子图_153改成All-Pair Almost Shortest Path(APASP)_子图_154

对k层图使用这个优化后,All-Pair Almost Shortest Path(APASP)_时间复杂度_116为度数All-Pair Almost Shortest Path(APASP)_最短距离_156的点构成的集合,All-Pair Almost Shortest Path(APASP)_子图_157All-Pair Almost Shortest Path(APASP)_子图_158All-Pair Almost Shortest Path(APASP)_最短距离_159

我们假设All-Pair Almost Shortest Path(APASP)_时间复杂度_160,那么All-Pair Almost Shortest Path(APASP)_时间复杂度_161,跑一层的复杂度是All-Pair Almost Shortest Path(APASP)_算法_162,跑k层,复杂度就是All-Pair Almost Shortest Path(APASP)_算法_163。由于All-Pair Almost Shortest Path(APASP)_子图_164,所以这个复杂度永远不会比之前的All-Pair Almost Shortest Path(APASP)_算法_152更差。

论文:<www.cs.tau.ac.il/~zwick/papers/apasp.ps.gz>

oooooooooooooooooooooooorz