初学python记录:力扣2642. 设计可以求最短路径的图类

文章介绍了如何使用邻接列表表示有向带权图,并利用Dijkstra算法实现Graph类的shortestPath方法,计算从给定节点node1到node2的最小代价路径,若无路径则返回-1。
摘要由CSDN通过智能技术生成

题目:

给你一个有 n 个节点的 有向带权 图,节点编号为 0 到 n - 1 。图中的初始边用数组 edges 表示,其中 edges[i] = [fromi, toi, edgeCosti] 表示从 fromi 到 toi 有一条代价为 edgeCosti 的边。

请你实现一个 Graph 类:

  • Graph(int n, int[][] edges) 初始化图有 n 个节点,并输入初始边。
  • addEdge(int[] edge) 向边集中添加一条边,其中 edge = [from, to, edgeCost] 。数据保证添加这条边之前对应的两个节点之间没有有向边。
  • int shortestPath(int node1, int node2) 返回从节点 node1 到 node2 的路径 最小 代价。如果路径不存在,返回 -1 。一条路径的代价是路径中所有边代价之和。

思考:

初始化图和向图中添加边都很好解决,用邻接列表表示图即可。

shortestPath方法是求一个节点到另一个节点的路径最小代价,很容易联想到迪杰斯特拉算法(确定一个起点,求得这个起点到所有节点的最短路径):

1. 数组s记录已求出最短路径的顶点,数组u记录还未求出最短路径的顶点,数组dis记录起点到所有节点的最短路径。初始时,s=(起点),u=(除起点外所有节点),dis中起点对应的值为0,其他节点对应的值为∞。

2. 遍历s中的点:当前访问的s中的点设为i,访问邻接列表中s相邻的所有点x,若dis[i]+相邻边代价<dis[x],即 起点到点i的最短距离+i到x的边的距离<当前起点到点x的最短距离,则更新dis[x]。

3. 更新完一轮dis[x]后(点i相邻的点x全部判断完了),取u中对应dis最小的点放入s中,继续进行步骤2,直至s中全部点都访问过了或u已经空了。

4. 最后返回dis[node2],若值为无穷大则返回-1.

代码如下:

class Graph(object):

    def __init__(self, n, edges):
        """
        :type n: int
        :type edges: List[List[int]]
        """
        self.n = n
        self.graph = [[] for _ in range(0, n)]    # 初始化邻接列表
        for from_i, to_i, cost in edges:
            self.graph[from_i].append((to_i, cost))    # 将每个边加入邻接列表
 

    def addEdge(self, edge):
        """
        :type edge: List[int]
        :rtype: None
        """
        self.graph[edge[0]].append((edge[1], edge[2]))


    def shortestPath(self, node1, node2):
        """
        :type node1: int
        :type node2: int
        :rtype: int
        """
        # Dijkstra
        # 数组S记录已求出最短路径的顶点
        # 数组U记录还未求出最短路径的顶点
        n = self.n
        s = [node1]   
        u = [node for node in range(0, n) if node != node1]
        # 数组dis表示起点到各个点的最短路径
        dis = [float ('inf')] * (n)
        dis[node1] = 0
        i = 0
        while True:
            # 若s中所有点都被判断过了或者u为空,退出循环
            if i >= len(s) or not u:     
                break
                
            for x, y in self.graph[s[i]]:   # 访问当前点的邻接点x
                if y+dis[s[i]] < dis[x]:   
                    dis[x] = y+dis[s[i]]     # 更新起点到点x的最短路径
            
            # 取出u中dis最短的点,加入s
            idx = u[0]
            for x in u:
                if dis[x] < dis[idx]:
                    idx = x
            s.append(idx)
            u.remove(idx)

            i += 1    # 开始下一轮循环

        return dis[node2] if dis[node2] != float ('inf') else -1

提交通过:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值