Задача имеет оптимальную подструктуру. Чтобы найти самый длинный путь из вершины c
в вершину z
, нам сначала нужно найти самый длинный путь из c
ко всем предшественникам z
. Каждая из них представляет собой еще одну меньшую подзадачу (самый длинный путь от c
до конкретного предшественника).
Обозначим предшественников z
как u1,u2,...,uk
и dist[z]
как самый длинный путь от c
до z
, затем dist[z]=max(dist[ui]+w(ui,z))
..
Вот иллюстрация с тремя предшественниками, в которых не указаны веса наборов ребер:
![введите здесь описание изображения](https://i.stack.imgur.com/GnwnX.jpg)
Таким образом, чтобы найти самый длинный путь к z
, нам сначала нужно найти самый длинный путь к его предшественникам и взять максимум (их значения плюс веса ребер до z
).
Это требует, чтобы каждый раз, когда мы посещаем вершину u
, все предшественники u
были проанализированы и вычислены.
Итак, вопрос: для любой вершины u
, как убедиться, что после того, как мы установим dist[u]
, dist[u]
никогда не изменится позже? Скажем иначе: как убедиться, что мы рассмотрели все пути от c
до u
, прежде чем рассматривать любое ребро, берущее начало в u
?
Поскольку граф ацикличен, мы можем гарантировать это условие, найдя топологическую сортировку над графом. топологическая сортировка похожа на цепочку вершин, где все ребра указывают слева направо. Итак, если мы находимся в вершине vi
, то мы рассмотрели все пути, ведущие к vi
, и получили окончательное значение dist[vi]
.
Временная сложность: топологическая сортировка занимает O(V+E)
. В худшем случае, когда z
является листом, а все остальные вершины указывают на него, мы посетим все ребра графа, что даст O(V+E)
.
person
Xline
schedule
18.11.2014