弗洛伊德(Floyd)算法

Dijkstra解决的是单源路径最短,即我们只能求某一点到其他所有点的最小距离。
而Floyd算法可以求任意两点间的最小距离;

单源最短路径一定能用Floyd算法去解,但是Floyd时间复杂度比迪杰斯特拉要高,所以一般只有多源最短路径采用Floyd算法

基本思想:

这是一个动态规划的思想,核心思想为,从A到B只经过前N个中转站所能获得的最小距离为多少

可以想象到,这个算法就是一个包含三个循环的dp问题,第一层遍历所有的节点作为中转站,第二三层分别遍历起点和终点。 所以Floyd算法又被称为五行代码的最小路径算法。

两个矩阵
  • 距离矩阵,记录起点到终点的最小距离。
  • 前驱矩阵,当以stopstop为中转站更新startstart和endend之间的距离时,更新pre[start][end] = stop, 表示starend路径中,end前一个点为stop,这个矩阵的作用为了找出最短路径的具体路径。
三层遍历

以前N个点为中转站更新所有起点终点的距离

for stop in range(N+1):
            for start in range(N+1):
                for end in range(N+1):
                    #更新距离和前驱
                    if dp[start][stop] + dp[stop][end] < dp[start][end]:
                        dp[start][end] = dp[start][stop] + dp[stop][end]
                        pre[start][end] = stop

举个例子
还是这道题 743. Network Delay Time


class Solution(object):
    def networkDelayTime(self, times, N, K):
        """
        :type times: List[List[int]]
        :type N: int
        :type K: int
        :rtype: int
        """
        # 距离矩阵
        dp = [[float("inf")] * (N+1) for _ in range(N+1)]
        for start, end, distance in times:
            dp[start][end] = distance
        for i in range(N+1):
            dp[i][i] = 0

        # 前驱点矩阵
        pre = [[i for i in range(N+1)] for j in range(N+1)]

        # 遍历每一个中转站
        for stop in range(N+1):
            for start in range(N+1):
                for end in range(N+1):
                    #更新距离和前驱
                    if dp[start][stop] + dp[stop][end] < dp[start][end]:
                        dp[start][end] = dp[start][stop] + dp[stop][end]
                        pre[start][end] = stop

        result = max(dp[K][i] for i in range(1, N+1))

        # 查看2 到 4的路径
        # for line in pre:
        #     print(line)
        # path, end = [4], 4
        # while(end != pre[2][end]):
        #     end = pre[2][end]
        #     path.append(end)
        # print(path)
        return result if result != float("inf") else -1

你可能感兴趣的:(算法与数据结构)