Алгоритм Дейкстры — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
м
Строка 1: Строка 1:
В [[Ориентированный граф|ориентированном]] взвешенном [[Основные определения: граф, ребро, вершина, степень, петля, путь, цикл|графе]] <tex>G = (V, E)</tex>, вес [[Основные определения: граф, ребро, вершина, степень, петля, путь, цикл|рёбер]] которого неотрицателен и определяется весовой функцией <tex>w : E \to \mathbb{R}</tex>, алгоритм Дейкстры находит длины кратчайших [[Основные определения: граф, ребро, вершина, степень, петля, путь, цикл|путей]] из заданной [[Основные определения: граф, ребро, вершина, степень, петля, путь, цикл|вершины]] <tex>s</tex> до всех остальных.
+
{{Задача
 +
|definition=Для заданного взвешенного графа <tex>G = (V, E)</tex> найти кратчайшие пути из заданной вершины <tex> s </tex> до всех остальных вершин. Веса всех рёбер неотрицательны.
 +
}}
  
 
== Алгоритм ==
 
== Алгоритм ==
 +
В [[Ориентированный граф|ориентированном]] взвешенном [[Основные определения: граф, ребро, вершина, степень, петля, путь, цикл|графе]] <tex>G = (V, E)</tex>, вес [[Основные определения: граф, ребро, вершина, степень, петля, путь, цикл|рёбер]] которого неотрицателен и определяется весовой функцией <tex>w : E \to \mathbb{R}</tex>, алгоритм Дейкстры находит длины кратчайших [[Основные определения: граф, ребро, вершина, степень, петля, путь, цикл|путей]] из заданной [[Основные определения: граф, ребро, вершина, степень, петля, путь, цикл|вершины]] <tex>s</tex> до всех остальных.<br>
 
В алгоритме поддерживается множество вершин <tex>U</tex>, для которых уже вычислены длины кратчайших путей до них из <tex>s</tex>. На каждой итерации основного цикла выбирается вершина <tex> u \notin U</tex>, которой на текущий момент соответствует минимальная оценка  кратчайшего пути. Вершина <tex>u</tex> добавляется в множество <tex>U</tex> и производится релаксация всех исходящих из неё рёбер.
 
В алгоритме поддерживается множество вершин <tex>U</tex>, для которых уже вычислены длины кратчайших путей до них из <tex>s</tex>. На каждой итерации основного цикла выбирается вершина <tex> u \notin U</tex>, которой на текущий момент соответствует минимальная оценка  кратчайшего пути. Вершина <tex>u</tex> добавляется в множество <tex>U</tex> и производится релаксация всех исходящих из неё рёбер.
  
 
== Псевдокод ==
 
== Псевдокод ==
<code>Для всех</code> <tex>u \in V</tex>
+
'''func''' dijkstra(s)''':'''
:  <tex>d[u] \gets \infty</tex>
+
    '''for''' i = 0 '''to''' n                      <font color="green">// n {{---}} количество вершин в графе</font>
<tex>d[s] \gets 0\</tex><br>
+
        d[v] = <tex>\infty</tex>
<tex> U \gets \emptyset</tex><br>
+
        used[v] = ''false''
<code>Пока</code> <tex>\exists v \notin U</tex>
+
    d[s] = 0
: <code>Пусть</code> <tex>v \notin U : d[v]</tex> <code> минимальный </code>
+
    '''for''' i = 0 '''to''' n
: <code>Для всех</code> <tex>u \notin U</tex> <code>таких, что</code> <tex>vu \in E</tex>
+
        v = ''null''
:: <code>если</code> <tex> d[u] > d[v] + w(vu)</tex> <code>то</code>
+
        '''for''' j = 0 '''to''' n                  <font color="green">// найдем вершину с минимальным расстоянием</font>
:::  <tex>d[u] \gets d[v] + w (vu)</tex>
+
            '''if''' !used[j] '''and''' (v == ''null'' '''or''' d[j] < d[v])
:  <tex>U \gets v </tex>
+
                v = j
 +
        '''if''' d[v] == <tex>\infty</tex>
 +
            '''break'''
 +
        used[v] = ''true''
 +
        '''for''' e : исходящие из ''v'' рёбра    <font color="green">// произведём релаксацию по всем рёбрам, исходящим из ''v''</font>
 +
            '''if''' d[v] + e.len < d[e.to]
 +
                d[e.to] = d[v] + e.len
  
 
== Обоснование корректности ==
 
== Обоснование корректности ==

Версия 18:41, 19 декабря 2015

Задача:
Для заданного взвешенного графа [math]G = (V, E)[/math] найти кратчайшие пути из заданной вершины [math] s [/math] до всех остальных вершин. Веса всех рёбер неотрицательны.


Алгоритм

В ориентированном взвешенном графе [math]G = (V, E)[/math], вес рёбер которого неотрицателен и определяется весовой функцией [math]w : E \to \mathbb{R}[/math], алгоритм Дейкстры находит длины кратчайших путей из заданной вершины [math]s[/math] до всех остальных.
В алгоритме поддерживается множество вершин [math]U[/math], для которых уже вычислены длины кратчайших путей до них из [math]s[/math]. На каждой итерации основного цикла выбирается вершина [math] u \notin U[/math], которой на текущий момент соответствует минимальная оценка кратчайшего пути. Вершина [math]u[/math] добавляется в множество [math]U[/math] и производится релаксация всех исходящих из неё рёбер.

Псевдокод

func dijkstra(s):
    for i = 0 to n                       // n — количество вершин в графе
        d[v] = [math]\infty[/math]
        used[v] = false
    d[s] = 0
    for i = 0 to n
        v = null
        for j = 0 to n                   // найдем вершину с минимальным расстоянием
            if !used[j] and (v == null or d[j] < d[v])
                v = j
        if d[v] == [math]\infty[/math]
            break
        used[v] = true
        for e : исходящие из v рёбра     // произведём релаксацию по всем рёбрам, исходящим из v
            if d[v] + e.len < d[e.to]
                d[e.to] = d[v] + e.len

Обоснование корректности

Теорема:
Пусть [math]G = (V, E)[/math] — ориентированный взвешенный граф, вес рёбер которого неотрицателен, [math]s[/math] — стартовая вершина. Тогда после выполнения алгоритма Дейкстры [math]d(u) = \rho(s, u)[/math] для всех [math]u[/math], где [math]\rho(s, u)[/math] — длина кратчайшего пути из вершины [math]s[/math] в вершину [math]u[/math]
Доказательство:
[math]\triangleright[/math]

Докажем по индукции, что в момент посещения любой вершины [math]u[/math], [math]d(u) = \rho(s, u)[/math].

  • На первом шаге выбирается [math]s[/math], для нее выполнено: [math]d(s) = \rho(s, s) = 0[/math]
  • Пусть для [math]n[/math] первых шагов алгоритм сработал верно и на [math]n + 1[/math] шагу выбрана вершина [math]u[/math]. Докажем, что в этот момент [math]d(u) = \rho(s, u)[/math]. Для начала отметим, что для любой вершины [math]v[/math], всегда выполняется [math]d(v) \geqslant \rho(s, v)[/math] (алгоритм не может найти путь короче, чем кратчайший из всех существующих). Пусть [math]P[/math] — кратчайший путь из [math]s[/math] в [math]u[/math], [math]v[/math] — первая непосещённая вершина на [math]P[/math], [math]z[/math] — предшествующая ей (следовательно, посещённая). Поскольку путь [math]P[/math] кратчайший, его часть, ведущая из [math]s[/math] через [math]z[/math] в [math]v[/math], тоже кратчайшая, следовательно [math]\rho(s, v) = \rho(s, z) + w(zv)[/math]. По предположению индукции, в момент посещения вершины [math]z[/math] выполнялось [math]d(z) = \rho(s, z)[/math], следовательно, вершина [math]v[/math] тогда получила метку не больше чем [math]d(z) + w(zv) = \rho(s, z) + w(zv) = \rho(s, v)[/math], следовательно, [math]d(v) = \rho(s, v)[/math]. С другой стороны, поскольку сейчас мы выбрали вершину [math]u[/math], её метка минимальна среди непосещённых, то есть [math]d(u) \leqslant d(v) = \rho(s, v) \leqslant \rho(s, u)[/math], где второе неравенсто верно из-за ранее упомянутого определения вершины [math]v[/math] в качестве первой непосещённой вершины на [math]P[/math], то есть вес пути до промежуточной вершины не превосходит веса пути до конечной вершины вследствие неотрицательности весовой функции. Комбинируя это с [math]d(u) \geqslant \rho(s, u)[/math], имеем [math]d(u) = \rho(s, u)[/math], что и требовалось доказать.
  • Поскольку алгоритм заканчивает работу, когда все вершины посещены, в этот момент [math]d(u) = \rho(s, u)[/math] для всех [math]u[/math].
[math]\triangleleft[/math]

Оценка сложности

Основной цикл выполняется [math]V[/math] раз. Релаксация выполнится всего [math]E[/math] раз. В реализации алгоритма присутствует функция выбора вершины с минимальным значением [math]d[/math], асимптотика её работы зависит от реализации.

Таким образом:

Структура данных Время работы
Наивная реализация [math]O(V^2+E)[/math]
Двоичная куча [math]O(E\log{V})[/math]
Фибоначчиева куча [math]O(V\log{V}+E)[/math]

Источники

  • Кормен, Томас Х., Лейзерсон, Чарльз И., Ривест, Рональд Л., Штайн Клиффорд Алгоритмы: построение и анализ, 2-е издание. Пер. с англ. — М.:Издательский дом "Вильямс", 2010. — 1296 с.: ил. — Парал. тит. англ. — ISBN 978-5-8459-0857-5 (рус.)
  • Википедия — свободная энциклопедия