python 实现迪杰斯特拉算法 + 应用 leetcode 题解 阈值距离最小邻居城市

迪捷斯德拉算法 (借助小根堆)

堆的简单使用可参考,我的博客https://blog.csdn.net/qq_46258829/article/details/134386437?spm=1001.2014.3001.5501

1.构建邻接表(邻接矩阵也可)

形如 本节点到自身距离可自行设定 (各人习惯,下面将演示先全设为inf 然后将自身再设为0)

# 初始化 (自己到自己设为 inf(无限)
[inf, inf, inf, inf, inf]
[inf, inf, inf, inf, inf]
[inf, inf, inf, inf, inf]
[inf, inf, inf, inf, inf]
[inf, inf, inf, inf, inf]

# 初始化 (自己到自己设为0)

[0, inf, inf, inf, inf]
[inf, 0, inf, inf, inf]
[inf, inf, 0, inf, inf]
[inf, inf, inf, 0, inf]
[inf, inf, inf, inf, 0]

邻接表结构体初始化

# 邻接表 初始化
adjgraph = [[float('inf')] *(n) for _ in range(n)]
for i,j,val in edges:
    adjgraph[i][j] = val
    adjgraph[j][i] = val
res = [float('inf'),0]

2.算法主体

首先初始化起点到所有点的距离 dist,默认为 inf,然后定义自己到自己距离为 0.

将 节点 和 到原点的距离信息,存成 list 格式:[节点,到原点距离],然后类似bfs,将它存入大list。

从大list中,pop 出 当前节点curr 和 当前节点到原点距离distance。

然后开始探索邻居。

先比较 结果dist 和 distance 的关系,若前<后,直接跳过。

if dis[curr] < distance:

   continue

然后再比较(source->next_node 的距离)和(source-> curr + curr -> next_node 的距离).如果大于,那么更新

 if adjgraph[curr][next_node] != float('inf') and dis[next_node] > distance + adjgraph[curr][next_node]:

      dis[next_node] = dis[curr]+ adjgraph[curr][next_node]
      heapq.heappush(q,[dis[next_node],next_node])

完整代码

        # 邻接表
        adjgraph = [[float('inf')] *(n) for _ in range(n)]
        for i,j,val in edges:
            adjgraph[i][j] = val
            adjgraph[j][i] = val
        res = [float('inf'),0]
        
        for s in range(n):
            # 存储从 s 出发,到各个节点的位置
            dis = [float('inf') for _ in range(n)]
            # 自身距离设为0 如果想设为 inf 可不加这行
            # dis[s] = 0
            # 借助堆实现
            q = [] 
            heapq.heappush(q,[0,s]) # 小根堆
            while q:
                # 从 q 中提取 curr 到原点距离,以及当前 curr 节点
                distance,curr = heapq.heappop(q) 
                # 如果存储的已经是最小的,无需更新,跳过即可
                if dis[curr] < distance: 
                   continue
             
                for next_node in range(n):
                  # curr 到 next_node 的距离是存在的,不是无穷的
                  # s 到 next_node 的距离,如果大于 curr 的距离 + curr 到 next_node 的距离。 
                    if adjgraph[curr][next_node] != float('inf') and \
                       dis[next_node] > distance + adjgraph[curr][next_node]:
                        # 更新
                        dis[next_node] = dis[curr]+ adjgraph[curr][next_node]
                        heapq.heappush(q,[dis[next_node],next_node])
            # 显示将结果
            print(s,dis)

1334.阈值距离内邻居最少城市

有 n 个城市,按从 0 到 n-1 编号。给你一个边数组 edges,其中 edges[i] = [fromi, toi, weighti] 代表 fromi 和 toi 两个城市之间的双向加权边,距离阈值是一个整数 distanceThreshold

返回能通过某些路径到达其他城市数目最少、且路径距离 最大 为 distanceThreshold 的城市。如果有多个这样的城市,则返回编号最大的城市。

注意,连接城市 i 和 j 的路径的距离等于沿该路径的所有边的权重之和。

题解:循环所有节点,把每一个都当成起点,然后应用 迪杰斯特拉算法,然年选出距离最小的即结果

class Solution:
    def findTheCity(self, n, edges, distanceThreshold):
        # 邻接表
        adjgraph = [[float('inf')] *(n) for _ in range(n)]
        for i,j,val in edges:
            adjgraph[i][j] = val
            adjgraph[j][i] = val
        res = [float('inf'),0]
        for s in range(n):
            dis = [float('inf') for _ in range(n)]
            dis[s] = 0
            q = [] 
            heapq.heappush(q,[0,s]) 
            while q:
                distance,curr = heapq.heappop(q) 
                if dis[curr] < distance: 
                     continue
                for next_node in range(n):
                    if adjgraph[curr][next_node] != float('inf') and \
                       dis[next_node] > distance + adjgraph[curr][next_node]:
                        
                        dis[next_node] = dis[curr]+ adjgraph[curr][next_node]
                        heapq.heappush(q,[dis[next_node],next_node])
            cont = 0
            for i in range(n):
                if dis[i] <= distanceThreshold: 
                    cont+= 1
            if cont <= res[0]:
                res[0] = cont
                res[1] = s
        
        return res[1]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

01_

感谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值