Алгоритм Флойда — Уоршалла — различия между версиями
Smolcoder (обсуждение | вклад) |
Smolcoder (обсуждение | вклад) (→Доказательство) |
||
Строка 14: | Строка 14: | ||
W[i][j] = W[i][j] or (W[i][k] and W[k][j]) | W[i][j] = W[i][j] or (W[i][k] and W[k][j]) | ||
=== Доказательство === | === Доказательство === | ||
− | <wikitex>Назовем ''промежуточной'' вершину некоторого пути $p = \left \langle v_0, v_1, \dots, v_k \right \rangle$, принадлежащую множеству вершин этого пути и отличающуюся от начальной и конечной вершин, то есть принадлежащую $\left \{ v_1, v_2, \dots, v_{k-1} \right \}$ | + | <wikitex>Назовем ''промежуточной'' вершину некоторого пути $p = \left \langle v_0, v_1, \dots, v_k \right \rangle$, принадлежащую множеству вершин этого пути и отличающуюся от начальной и конечной вершин, то есть принадлежащую $\left \{ v_1, v_2, \dots, v_{k-1} \right \}$. Рассмотрим произвольную пару вершин $i, j \in V$ и все пути между ними, промежуточные вершины которых принадлежат множеству вершин с номерами $\left \{ 1, 2, \dots, k \right \}$. Пусть $p$ - кратчайший из них. Рассмотрим случаи: |
+ | * $k$ не является промежуточной вершиной пути $p$. Тогда все его промежуточные пути принадлежат множеству вершин с номерами $\left \{ 1, 2, \dots, k-1 \right \} \subset \left \{ 1, 2, \dots, k \right \}$, что и требуется. | ||
+ | * $k$ является промежуточной вершиной пути $p$. Тогда этот путь можно разбить на два пути: $i \xrightarrow{p_1} k \xrightarrow{p_2} j$. Как $p_1$, так и $p_2$ являются кратчайшими путями между соответствующими вершинами $i, k$ и $k, j$ с промежуточными вершинами из множества $\left \{ 1, 2, \dots, k-1 \right \} \subset \left \{ 1, 2, \dots, k \right \}$ (так как вершина $k$ - либо конечная, либо начальная, то она не может быть в множестве по нашему определению). Действительно, если они не являются таковыми, то заменим эти подпути пути $p$ на кратчайшие. Тогда сам путь $p$ не будет кратчайшим, что является противоречием. | ||
+ | Во время работы алгоритма будут просмотрены все возможные разбиения на соответствующие пути для каждой пары вершин и выбран лучший из них. По его окончании транзитивное замыкание будет построено корректно. | ||
</wikitex> | </wikitex> | ||
+ | |||
=== Сложность алгоритма === | === Сложность алгоритма === | ||
Три вложенных цикла работают за время <tex>\sum\limits_{n}\sum\limits_{n}\sum\limits_{n}O(1) = O(n^3)</tex>, | Три вложенных цикла работают за время <tex>\sum\limits_{n}\sum\limits_{n}\sum\limits_{n}O(1) = O(n^3)</tex>, |
Версия 11:22, 12 декабря 2011
Содержание
Задача
Пусть дано отношение на множестве . Необходимо построить его транзитивное замыкание .
Алгоритм
Сформулируем нашу задачу в терминах графов: рассмотрим граф
, соответствующий отношению . Тогда необходимо найти все пары вершин , соединенных некоторым путем. Иными словами, требуется построить новое отношение , которое будет состоять из всех пар таких, что найдется последовательность , где .Псевдокод
Изначально матрица
заполняется соответственно отношению , то есть . Затем внешним циклом перебираются все элементы множества и для каждого из них, если он может использоваться, как промежуточный для соединения двух элементов и , отношение расширяется добавлением в него пары .for k = 1 to n for i = 1 to n for j = 1 to n W[i][j] = W[i][j] or (W[i][k] and W[k][j])
Доказательство
<wikitex>Назовем промежуточной вершину некоторого пути $p = \left \langle v_0, v_1, \dots, v_k \right \rangle$, принадлежащую множеству вершин этого пути и отличающуюся от начальной и конечной вершин, то есть принадлежащую $\left \{ v_1, v_2, \dots, v_{k-1} \right \}$. Рассмотрим произвольную пару вершин $i, j \in V$ и все пути между ними, промежуточные вершины которых принадлежат множеству вершин с номерами $\left \{ 1, 2, \dots, k \right \}$. Пусть $p$ - кратчайший из них. Рассмотрим случаи:
- $k$ не является промежуточной вершиной пути $p$. Тогда все его промежуточные пути принадлежат множеству вершин с номерами $\left \{ 1, 2, \dots, k-1 \right \} \subset \left \{ 1, 2, \dots, k \right \}$, что и требуется.
- $k$ является промежуточной вершиной пути $p$. Тогда этот путь можно разбить на два пути: $i \xrightarrow{p_1} k \xrightarrow{p_2} j$. Как $p_1$, так и $p_2$ являются кратчайшими путями между соответствующими вершинами $i, k$ и $k, j$ с промежуточными вершинами из множества $\left \{ 1, 2, \dots, k-1 \right \} \subset \left \{ 1, 2, \dots, k \right \}$ (так как вершина $k$ - либо конечная, либо начальная, то она не может быть в множестве по нашему определению). Действительно, если они не являются таковыми, то заменим эти подпути пути $p$ на кратчайшие. Тогда сам путь $p$ не будет кратчайшим, что является противоречием.
Во время работы алгоритма будут просмотрены все возможные разбиения на соответствующие пути для каждой пары вершин и выбран лучший из них. По его окончании транзитивное замыкание будет построено корректно. </wikitex>
Сложность алгоритма
Три вложенных цикла работают за время
, то есть алгоритм имеет кубическую сложность.Ссылки
- Реализация алгоритма Флойда на С++
- Реализация алгоритма Флойда на Delphi
- Визуализатор
- Википедия — свободная энциклопедия
Источники
- Романовский И. В. Дискретный анализ: Учебное пособие для студентов, специализирующихся по прикладной математике и информатике. Изд. 3-е. — СПб.: Невский диалект, 2003. — 320 с. — ISBN 5-7940-0114-3.