SPFA 算法 & 网络延迟时间

36 篇文章 2 订阅
30 篇文章 0 订阅

 

SPFA(Shortest Path Faster Algorithm) 算法是 Bellman-Ford算法 的队列优化算法的别称,通常用于求含负权边的单源最短路径,以及判负权环。SPFA 最坏情况下复杂度和朴素 Bellman-Ford 相同,为 O(VE)。

算法优点

        1.时间复杂度比普通的Dijkstra和Ford

        2.能够计算有负权的图,即:路径减小时,会进行判断。

算法思想:

我们用数组记录每个结点的最短路径估计值,用邻接表来存储图G。

我们采取的方法是动态逼近法:

1.设立一个先进先出的队列用来保存待优化的结点。

2.优化时每次取出队首结点u,并且用u点当前的最短路径估计值对离开u点所指向的结点v进行判断,如果v点的最短路径估计值有所上升或下降,且v点不在当前的队列中,就将v点放入队尾。

3.这样不断从队列中取出结点来进行松弛操作,直至队列空为止

期望的时间复杂度O(ke), 其中k为所有顶点进队的平均次数,可以证明k一般小于等于2。

实现方法:

1、存入图。可以使用链式前向星或者vocter

2、开一个队列,先将开始的节点放入。

3、每次从队列中取出一个节点X,遍历与X相通的Y节点,查询比对  Y的长度 和 X的长度+ 边(X,Y)的长度 如果X的长度+ 边(X,Y) Y的长度,说明需要更新操作。

  • 存入最短路。

  • 由于改变了原有的长度,所以需要往后更新,与这个节点相连的最短路。(即:判断下是否在队列,在就不用重复,不在就加入队列,等待更新)。

  • 在这期间可以记录这个节点的进队次数,判断是否存在负环。

4、直到队空。

判断有无负环:如果某个点进入队列的次数超过N次则存在负环

参考:http://keyblog.cn/article-21.html

【题目描述】

有 N 个网络节点,标记为 1 到 N。

给定一个列表 times,表示信号经过有向边的传递时间。 times[i] = (u, v, w),其中 u 是源节点,v 是目标节点, w 是一个信号从源节点传递到目标节点的时间。

现在,我们向当前的节点 K 发送了一个信号。需要多久才能使所有节点都收到信号?如果不能使所有节点收到信号,返回 -1。

注意:

  • N 的范围在 [1, 100] 之间。
  • K 的范围在 [1, N] 之间。
  • times 的长度在 [1, 6000] 之间。
  • 所有的边 times[i] = (u, v, w) 都有 1 <= u, v <= N 且 0 <= w <= 100。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/network-delay-time/
 

    def networkDelayTime(self, times, N, K):

        def spfa():
            from collections import deque
            from collections import defaultdict
            edge_weight = {}
            next_edges = defaultdict(list)
            for u, v, w in times:
                edge_weight[(u, v)] = w
                next_edges[u].append(v)
            # 第一种实现方法
            # stack = deque()
            # stack.append(K)
            # path = [float('inf') for i in range(N + 1)]
            # path[K] = 0
            # while stack:
            #     cur = stack.popleft()
            #     if not next_edges.get(cur):
            #         continue
            #     for next in next_edges.get(cur):
            #         if path[cur] + edge_weight[(cur, next)] < path[next]:
            #             path[next] = path[cur] + edge_weight[(cur, next)]
            #             if next not in stack:
            #                 stack.append(next)
            # 第二种实现方法
            stack = [K]
            path = [float('inf')]*(N + 1)
            path[K] = 0
            while stack:
                new_stack = []
                for cur in stack:
                    if not next_edges.get(cur):
                        continue
                    for next in next_edges.get(cur):
                        if path[cur] + edge_weight[(cur, next)] < path[next]:
                            path[next] = path[cur] + edge_weight[(cur, next)]
                            if next not in new_stack:
                                new_stack.append(next)
                stack = new_stack
            return -1 if any(x == float('inf') for x in path[1:]) else max(path[1:])
        return spfa()

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值