当前位置: 首页 > news >正文

【算法】图论 —— Dijkstra算法 python



引入


非负权边单源最短路

时间复杂度 O( m l o g n mlogn mlogn)


模板

https://www.luogu.com.cn/problem/P4779

import heapq as hq  
  
def dijkstra(s):  
    # dis表示从s到i的最短路  
    dis = [float('inf')] * (n + 1)  
    # vis表示i是否出队列  
    vis = [0] * (n + 1)  
    q = []  
    dis[s] = 0  
    hq.heappush(q, (0, s))  
    while q:  
        d, u = hq.heappop(q)  
        if vis[u]:  
            continue  
        vis[u] = 1  
        for v, w in g[u]:  
            dis[v] = min(dis[v], dis[u] + w)  
            hq.heappush(q, (dis[v], v))  
    for i in range(1, n + 1):  
        if dis[i] == float('inf'):  
            dis[i] = -1  
    return dis[1:]  
  
n, m, s= map(int, input().split())  
g = [[] for _ in range(n + 1)]  
for _ in range(m):  
    u, v, w = map(int, input().split())  
    g[u].append((v, w))  
print(*dijkstra(s))


实战演练


L2 001 紧急救援

维护多个数组并得到具体路径

import heapq as hq  
import sys  
input = sys.stdin.readline  
inf = float('inf')  
  
def dijkstra(s, ed):  
    q = []  
    vis = [0] * n  
    dis = [inf] * n  
    pre = [-1] * n  
    cnt = [0] * n  # 最短路径数量  
    res = [0] * n  # 能召集的最大救援队数量  
  
    dis[s] = 0  
    cnt[s] = 1  
    res[s] = a[s]  
    hq.heappush(q, (0, s))  
  
    while q:  
        d, u = hq.heappop(q)  
        if u == ed:  
            return dis[ed], cnt[ed], res[ed], pre  
        if vis[u]:  
            continue  
        vis[u] = 1  
        for (v, w) in g[u]:  
            if dis[v] > dis[u] + w:  
                dis[v] = dis[u] + w  
                cnt[v] = cnt[u]  
                res[v] = res[u] + a[v]  
                pre[v] = u  
                hq.heappush(q, (dis[v], v))  
            elif dis[v] == dis[u] + w:  
                cnt[v] += cnt[u]  # 更新最短路径数量  
                if res[v] < res[u] + a[v]:  
                    res[v] = res[u] + a[v]  
                    pre[v] = u  
    return -1, -1, -1, pre  
  
n, m, s, ed = map(int, input().split())  
a = list(map(int, input().split()))  
g = [[] for _ in range(n)]  
for _ in range(m):  
    u, v, w = map(int, input().split())  
    g[u].append((v, w))  
    g[v].append((u, w))  # 无向图  
  
dist, cnt, res, pre = dijkstra(s, ed)  
if dist != -1:  
    print(cnt, res)  
    path = []  
    while ed != -1:  # 从终点回溯路径  
        path.append(ed)  
        ed = pre[ed]  
    path.reverse()  # 反转路径  
    print(' '.join(map(str, path)))


https://www.lanqiao.cn/problems/3818/learning/

import sys  
import heapq as hq  
input = sys.stdin.readline  
  
def get(c):  
    if c == '.':  
        return 0  
    else:  
        return ord(c) - ord('A') + 1  
  
def dijkstra():  
    q = []  
    dis = [[float('inf')] * m for _ in range(n)]  
    vis = [[0] * m for _ in range(n)]  
    dis[x1][y1] = 0  
    hq.heappush(q, (0, x1, y1))  
    while q:  
        d, x, y = hq.heappop(q)  
        if x == x2 and y == y2:  
            return d  
        if vis[x][y]:  
            continue  
        vis[x][y] = 1  
        for dx, dy in [(1, 0), (-1, 0), (0, 1), (0, -1)]:  
            nx, ny = x + dx, y + dy  
            if 0 <= nx < n and 0 <= ny < m and a[nx][ny] != '#' and not vis[nx][ny]:  
                dis[nx][ny] = min(dis[nx][ny], dis[x][y] + get(a[nx][ny]))  
                hq.heappush(q, (dis[nx][ny], nx, ny))  
    return float('inf')  
  
n, m = map(int, input().split())  
x1, y1, x2, y2 = map(int, input().split())  
x1 -= 1  
x2 -= 1  
y1 -= 1  
y2 -= 1  
a = [input() for _ in range(n)]  
e = int(input())  
  
if e >= dijkstra():  
    print('Yes')  
else:  
    print('No')


https://ac.nowcoder.com/acm/contest/99909/E

对于每条边 ( u , v ) (u,v) (u,v),如果这条边在某条最短路上的话,则一定满足:
dis[u] + w + dis[v] == dis[n] ,即 最短路从 1 到 u ,再从 u 到 v ,再从 v 到 n 最短路从 1 到 u,再从 u 到 v,再从 v 到 n 最短路从1u,再从uv,再从vn。(或者是 u , v u,v u,v反过来)

import sys  
input = sys.stdin.readline  
inf = float('inf')  
import heapq as hp  
  
def dijkstra(s):  
    dis = [inf] * (n + 1)  
    vis = [0] * (n + 1)  
    q = [(0, s)]  
    dis[s] = 0  
    while q:  
        d, u = hp.heappop(q)  
        if vis[u]:  
            continue  
        vis[u] = 1  
        for v, w in g[u]:  
            if dis[v] > dis[u] + w:  
                dis[v] = dis[u] + w  
                hp.heappush(q, (dis[v], v))  
    return dis  
  
t = int(input())  
for _ in range(t):  
    n, m = map(int, input().split())  
    g = [[] for _ in range(n + 1)]  
    edge = []  
    for i in range(m):  
        u, v, w = map(int, input().split())  
        g[u].append((v, w))  
        g[v].append((u, w))  
        edge.append((u, v, w))  
  
    dis1 = dijkstra(1)  
    disn = dijkstra(n)  
    res = []  
    for u, v, w in edge:  
        # 检查是否在最短路径中  
        if dis1[u] != inf and disn[v] != inf and (dis1[u] + w + disn[v] == dis1[n]):  
            res.append('1')  
        elif dis1[v] != inf and disn[u] != inf and (dis1[v] + w + disn[u] == dis1[n]):  
            res.append('1')  
        else:  
            res.append('0')  
    print(''.join(res))


END
如果有更多问题或需要进一步的帮助,可以在评论区留言讨论哦!
如果喜欢的话,请给博主点个关注 谢谢

相关文章:

  • 【计算机网络】深入解析 HTTP 协议的概念、工作原理和通过 Fiddler 抓包查看 HTTP 请求/响应的协议格式
  • 在运维工作中,Lvs、nginx、haproxy工作原理分别是什么?
  • 音视频入门基础:RTP专题(16)——RTP封装音频时,音频的有效载荷结构
  • spring boot3-redis分库及配置
  • 微服务与消息队列RabbitMQ
  • Expo知识框架大全详解
  • DQN(Deep Q - Network)原理举例说明
  • 【量化策略】动量延续策略
  • 在Rocky Linux上安装Redis(DNF和源码安装)
  • 网络安全之端口扫描(一)
  • SpringBoot实现文件上传
  • 你为什么要写博客?
  • Linux系统编程--线程同步
  • WangEditor快速实现版
  • 在word下写公式
  • OneM2M:全球性的物联网标准-可应用于物联网中
  • [Kubernetes] 7控制平面组件
  • 排列组合定义及基本公式
  • C++11新特性 10.初始化列表、initializer_list
  • 嵌入式设备的功能安全和信息安全?
  • 太原做企业网站的/宁波seo软件免费课程
  • 商丘公司做网站/收录优美图片崩了
  • 个域名的网站建设方案书/谷歌推广app
  • 十堰市网站建设/搜索seo
  • 上传文件的网站/泰州seo公司
  • 汕头网站建设公司/网站关键词优化排名