• Johnson算法学习笔记


    (Johnson)算法学习笔记。

    在最短路的学习中,我们曾学习了三种最短路的算法,(Bellman-Ford)算法及其队列优化(SPFA)算法,(Dijkstra)算法。这些算法可以快速的求出单源最短路,即一个源点的最短路.

    (Floyd)算法,这个及其简短的算法,可以以(O(n^3))的复杂度算出任意一对点之间的最短路。

    我们发现,(floyd)算法的时间复杂度和边的数量没有多大的关系,也就是说,(floyd)使用的最优条件是稠密图。

    那么问题来了,如果我们面对一个点数非常多但是边数较少的图,我们该用什么算法呢?


    (johnson)出现了。

    (johnson)算法是一类用来处理多源最短路的算法,它的复杂度是(O(n*m*log_n))

    简单的来说,(johnson)算法是糅合的两大单源最短路算法的算法。

    (dijkstra)算法在算法界是一个公认非常好用的算法,只可惜其限制条件过多,必须没用负边才可以使用。

    (SPFA)就没有那么多限制了,它只用保证数据中不会出现负环即可,可是由于(spfa)算法及其不稳定,及其容易被卡成(O(n*m))的复杂度。

    (johnson)算法就利用了两大算法的优点。


    首先(johnson)先利用(SPFA)将所有的边处理一下,将负边权全都转成正边权。

    然后再每个点暴力跑(dijkatra)求出最短路。

    第二步利用(dijkstra)跑最短路是十分显然好懂的,问题就是第一步将负边改为正边。

    我们知道,直接将所有的负边加上一个极大值是错误的,我们要给所有的边加上一个合适的值。

    那么这个值是什么呢?

    我们先增加一个超级源,把所有点和它相连即可。

    然后,我们来以超级源为源点跑一遍(spfa)

    然后我们对于每一条边加上(spaf)跑完后的(dis[0][u]-dis[0][v])

    最后,把所有的(dis[u][v])减去(dis[0][u]-dis[u][v])还原。


    让我们来证明其正确性:

    1.边权不为负数。

    由于(dis[0][u]+w(u,v)>=dis[0][j])

    所以必有(dis[0][u]-dis[0][j]+w(u,v)>=0)

    所以边权必定大于等于(0),可以用(dijkstra)跑。

    2.还原的正确性。

    我们有一条集合为({A_1,A_2,A_3,,,,A_p})的最短路。

    我们对边权进行修改后,最短路改变的值为:(dis[0][A_1]-dis[0][A_2]+dis[0][A_2]-...-dis[0][A_p])

    即:(dis[0][A_1]-dis[0][A_p])

    所以,当我们修改一些权值时,任意两点之间的最短路改变的值是一个定值,即(dis[0][u]-dis[v])

    在最后的(dis[u][v])上减掉即可。

  • 相关阅读:
    JavaScript中的十种操作符
    数据类型即其相互转换
    理解CSS中position的各个值
    理解JavaScript中的this
    理解JavaScript中的回调函数
    hdu-1248-寒冰王座
    ny-71-独木舟上的旅行
    ny-47-过河问题
    ny-14-会场安排问题
    ny-47-喷水装置(一)
  • 原文地址:https://www.cnblogs.com/dsjkafdsaf/p/11379992.html
Copyright © 2020-2023  润新知