Dijkstra's algorithm (狄克斯特拉算法)

概要

狄克斯特拉算法是从一个顶点到其余各顶点的最短路径算法,用于不包含负边的有权图中的单源最短路径问题。
类似于BFS(宽度优先搜索)。

方法

  • 准备priority_queue(优先级队列),push起点和到其的最短距离的信息(起点为00, 其他顶点为∞)。因为使用了优先级队列,所以信息以最短距离顺序排序。
  • 重复以下的操作,直到优先级队列为空集。
    1. 提取优先级队列的先头元素(距离最短的元素)
    2. 如果所提取的元素中包含的距离信息大于所记录的最短距离,则该操作终止,并且操作返回到提取前导元素的操作。
    3. 扫描可以从那里移动的顶点,如果有可以更新最短距离的顶点,则更新该距离,然后将把走到该顶点的距离,顶点的信息push到优先队列。

复杂度为O(ElogV)。

伪代码

// V: 顶点集
// Q: 优先级队列 元素由(距离,目前到达顶点)构成
// d(v): 距起始顶点的最短路径的长度
// prev(v): 走最短路径时的前一个顶点

// 初始化
for (v <- V)
    d(v) <- (如果v=s代入0,其他代入∞)
    prev(v) <- (没有)
    Q(v) <- d(v)

// 计算
while ( Q不是空集 )
    从Q中取出Q(u)最小的顶点u
    if d(u) < 取出元素的距离
    for each ( 与顶点u存在相连接的边的顶点v(属于V) )
    alt <- d(u) + length(u, v)
    if ( d(v) > alt )
        d(v) <- alt
        prev(v) <- u
        Q(v) <- alt

Python代码

import heapq


class Dijkstra:

    def __init__(self, rote_map, start_point, goal_point=None):
        self.rote_map = rote_map
        self.start_point = start_point
        self.goal_point = goal_point

    def execute(self):
        num_of_city = len(self.rote_map)
        dist = [float("inf") for _ in range(num_of_city)]
        prev = [float("inf") for _ in range(num_of_city)]

        dist[self.start_point] = 0
        heap_q = []
        heapq.heappush(heap_q, (0, self.start_point))
        while len(heap_q) != 0:
            prev_cost, src = heapq.heappop(heap_q)

            if dist[src] < prev_cost:
                continue

            for dest, cost in self.rote_map[src].items():
                if cost != float("inf") and dist[dest] > dist[src] + cost:
                    dist[dest] = dist[src] + cost
                    heapq.heappush(heap_q, (dist[dest], dest))
                    prev[dest] = src
        if self.goal_point is not None:
            return self.get_path(self.goal_point, prev)
        else:
            return dist

    def get_path(self, goal, prev):
        path = [goal]
        dest = goal

        while prev[dest] != float("inf"):
            path.append(prev[dest])
            dest = prev[dest]

        return list(reversed(path))
# 使用方法
n = int(input())
s, t = map(int, input().split())
route_map = [dict() for _ in range(n)]
for i in range(n):
    u, v, a = map(int, input().split())
    u, v = u - 1, v - 1
    route_map[u][v] = a

# 返回从起点到每个顶点的最短距离的列表
dijkstra_result = Dijkstra(route_map, s - 1).execute()

# 从起点到终点的最短距离
dijkstra_result = Dijkstra(route_map, s - 1, t - 1).execute()

相关问题

Single Source Shortest Path

JOI 2008 予選 6 - 船旅(日语)

SoundHound Inc. Programming Contest 2018 -Masters Tournament–D Saving Snuuk(日语)

技術室奥プログラミングコンテスト #4 Day1 - don’t be late(日语)

JOI 2014 予選 5 - タクシー(日语)

JOI 2016 予選 5 - ゾンビ島(日语)

你可能感兴趣的:(Algorithm)