LC743. 网络延迟时间

弗洛伊德算法

def networkDelayTime(self, times, n, k):
        """
        :type times: List[List[int]]
        :type n: int
        :type k: int
        :rtype: int
        """
        INTMAX = 0x3f3f3f3f
        graph = [[INTMAX]*n for i in range(n)]
        for x,y,t in times:
            graph[x-1][y-1] = t
        for i in range(n):
            graph[i][i] = 0

        for l in range(n):                                         #经典floyed算法l作为中间点,不断更新经过l的两个节点的最短路径
            for i in range(n):
                for j in range(n):
                    if graph[i][j] > graph[i][l] + graph[l][j]:
                        graph[i][j] = graph[i][l] + graph[l][j]
        mint = -1
        for i in range(n):
            if graph[k-1][i] == INTMAX:               #这里表明如果遇到不能到达的节点直接返回-1
                return -1                                  
            mint = max(mint,graph[k-1][i])            #找由起点开始所有路径中最远的
        return mint

BFS

def networkDelayTime(times, n, k):
    mp = [{} for i in range(n + 1)]
    for u, v, t in times:               #邻接表记录可到达的节点以及所需时间
        mp[u][v] = t
    r = [-1 for i in range(n + 1)]      #记录开始节点到各个节点的最短路径长度
    r[k] = 0
    # 队列中存放 [结点,收到信号时间]
    s = deque([[k, 0]])
    while s:
        cur, t = s.popleft()            #当前节点,和当前节点到开始结点的路径长度
        for u, v in mp[cur].items():    #u是当前节点对应的邻居节点 v是它们之间的路径长度
            art = t + v                 #更新路径长度
            # 仅当结点未收到或收到时间比记录时间更早才更新并入队
            if r[u] == -1 or art < r[u]:#更新最短路径  (这里是和迪杰斯特拉算法不同的地方,如果后面的u比前面的u的距离短的话,依然是按顺序执行的,而迪杰斯特拉每次都是找到最短的那个节点开始)
                r[u] = art
                s.append([u, art])      #邻居节点和长度加入队列
    minT = -1
    for i in range(1, n + 1):
        if r[i] == -1:
            return -1
        minT = max(minT, r[i])          #返回最长的
    return minT

迪杰斯特拉算法(相比上面的广度优先的区别在于没有用到贪心算法的思想。)

def networkDelayTime(self, times, n, k):
        """
        :type times: List[List[int]]
        :type n: int
        :type k: int
        :rtype: int
        """
        INTMAX = 0x3f3f3f3f
        mp = [{} for i in range(n)]
        for u,v,t in times:                  #邻接表,作用是存储相邻边
            mp[u-1][v-1] = t
        s = [0]*n                            #访问数组
        r = [INTMAX]*n                       #距离记录
        r[k-1] = 0
        while True:
            cur,d = -1,INTMAX                #初始值
            for i,t in enumerate(r):         #每次都找还没被访问的离起始点最短的那个节点(贪心思想)
                if s[i] == 0 and t < d:
                    cur,d = i,t
            if cur == -1:                    #有连接的都访问过了
                break
            s[cur] = 1                       #把找到的最短的标记为访问过
            for u,v in mp[cur].items():      #更新最短的邻居节点距离起始点的距离
                r[u] = min(r[u],d+v)
        mint = -1
        for j in range(n):
            if r[j] == INTMAX:
                return -1
            mint = max(mint,r[j])
        return mint

堆优化迪杰斯特拉

def networkDelayTime(self, times, n, k):
        """
        :type times: List[List[int]]
        :type n: int
        :type k: int
        :rtype: int
        """
        INTMAX = 0x3f3f3f3f
        r = [INTMAX]*n 
        r[k-1] = 0
        mp = [{} for i in range(n)]
        for x,y,t in times:
            mp[x-1][y-1] = t 
        s = [[0,k-1]]
        heapq.heapify(s)                       #堆化
        while s:
            curt,node = heapq.heappop(s)       #每次弹出来的最小元素,而且是按照列表里第一个元素排序的(在这里就是时间最短的顺序)
            if curt > r[node]:                 #进栈的时候没能控制一定是最小的,所以加个判断,如果curt并不是最小的,那么跳过
                continue
            for neighbor,weight in mp[node].items():                      #查看邻居节点的情况
                if r[neighbor] > r[node] + weight:                        #有更短的入队
                    r[neighbor] = r[node]+weight                          #更新r
                    heapq.heappush(s,[r[neighbor],neighbor])
        mint = -1
        for j in range(n):
            if r[j] == INTMAX:
                return -1
            mint = max(mint,r[j])
        return mint

bellman-ford算法

def networkDelayTime(self, times, n, k):
        """
        :type times: List[List[int]]
        :type n: int
        :type k: int
        :rtype: int
        """
        INTMAX = 0x3f3f3f3f
        r = [INTMAX]*n 
        r[k-1] = 0
        for i in range(n-1):                 #松弛 图中节点个数减一次
            for x,y,t in times:						#这里是从x到y及权重 所以到y的路径长度应该等于到x的路径长度加上权重
                if r[y-1] > r[x-1] + t:
                    r[y-1] = r[x-1] + t 
        for x, y, t in times:                #再进行一次松弛操作,如果还有更新说明图中存在负权的环
	        if r[y - 1] > r[x - 1] + t:
	            return -1
        mint = -1
        for j in range(n):
            if r[j] == INTMAX:
                return -1
            mint = max(mint,r[j])
        return mint

SPFA,双端队列优化bellman-ford算法,用双端队列记录松弛过的节点,只有松驰过的节点才会对后面路径长度产生影响所以不是所有节点都需要更新

def networkDelayTime(self, times, n, k):
        """
        :type times: List[List[int]]
        :type n: int
        :type k: int
        :rtype: int
        """
        INTMAX = 0x3f3f3f3f
        r = [INTMAX]*n 
        r[k-1] = 0                                  
        mp = [{} for i in range(n)]
        for x, y, t in times:
            mp[x-1][y-1] = t 
        queue =deque([k-1])                           #记录松驰过的节点
        s = set()                                     #加上一个访问数组可以避免重复让相同的节点入队列,加快时间
        s.add(k-1)
        while queue:
            cur = queue.popleft()
            s.remove(cur)
            for neighbor, t in mp[cur].items():
                if r[neighbor] > r[cur] + t:
                    r[neighbor] = r[cur] + t 
                    if neighbor not in s:
                        s.add(neighbor)
                        queue.append(neighbor)
        mint = -1
        for i in range(n):
            if r[i] == INTMAX:
                return -1
            mint = max(mint,r[i])
        return mint
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值