Максимальный взвешенный путь между двумя вершинами в направленном ациклическом графе

Люблю некоторые рекомендации по этой проблеме:

G — ориентированный ациклический граф. Вы хотите перейти из вершины c в вершину z. Некоторые преимущества уменьшают вашу прибыль, а некоторые увеличивают ее. Как перейти от c к z, максимизируя прибыль. Какова временная сложность?

Спасибо!


person evenodd    schedule 17.11.2014    source источник


Ответы (3)


Задача имеет оптимальную подструктуру. Чтобы найти самый длинный путь из вершины c в вершину z, нам сначала нужно найти самый длинный путь из c ко всем предшественникам z. Каждая из них представляет собой еще одну меньшую подзадачу (самый длинный путь от c до конкретного предшественника).

Обозначим предшественников z как u1,u2,...,uk и dist[z] как самый длинный путь от c до z, затем dist[z]=max(dist[ui]+w(ui,z))..

Вот иллюстрация с тремя предшественниками, в которых не указаны веса наборов ребер:

введите здесь описание изображения

Таким образом, чтобы найти самый длинный путь к 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

Пусть f(u) будет максимальной прибылью, которую вы можете получить при переходе от c к u в вашей DAG. Затем вы хотите вычислить f(z). Это можно легко вычислить за линейное время, используя динамическое программирование/топологическую сортировку.

Инициализируйте f(u) = -infinity для каждого u, кроме c, и f(c) = 0 . Затем продолжите вычисление значений f в некотором топологическом порядке вашей DAG. Таким образом, поскольку порядок является топологическим, для каждого входящего ребра вычисляемого узла вычисляются другие конечные точки, поэтому просто выберите максимально возможное значение для этого узла, т. е. f(u) = max( f(v) + cost(v, u)) для каждого входящего ребра (v, u).

person AlexAlvarez    schedule 17.11.2014

Лучше использовать топологическую сортировку вместо Bellman Ford с момента его DAG.

Источник: - http://www.utdallas.edu/~sizheng/CS4349.d/l-notes.d/L17.pdf

ИЗМЕНИТЬ:-

G — это DAG с отрицательными ребрами.

Некоторые преимущества уменьшают вашу прибыль, а некоторые увеличивают вашу прибыль.

  • Края - увеличение прибыли - положительное значение
  • Края - уменьшение прибыли - отрицательное значение

После TS для каждой вершины U в порядке TS - расслабить каждое выходящее ребро.

dist[] = {-INF, -INF, ….}
dist[c] = 0 // source

for every vertex u in topological order
  if (u == z) break; // dest vertex
  for every adjacent vertex v of u
    if (dist[v] < (dist[u] + weight(u, v))) // < for longest path = max profit
      dist[v] = dist[u] + weight(u, v)

ans = dist[z];
person Mitesh Pathak    schedule 17.11.2014
comment
После выполнения топологической сортировки какой алгоритм дает путь с максимальным значением? - person evenodd; 18.11.2014
comment
Это правильно только тогда, когда вы ищете КРАТКИЕ пути. - person Xline; 18.11.2014
comment
@Xline согласился, вам нужно вычислить самый длинный путь ... см. мой обновленный ответ - person Mitesh Pathak; 18.11.2014
comment
@MiteshPathak также я ищу самый длинный путь не от любого узла, а между двумя конкретными узлами. - person evenodd; 18.11.2014
comment
@evenodd В этом случае прервите цикл перед циклом for, когда (v == dest node) - person Mitesh Pathak; 18.11.2014
comment
@evenodd обновил мой ответ. Это должно быть u == узел назначения - person Mitesh Pathak; 18.11.2014
comment
Проблема в том, что если прерывается, когда он достигает узла назначения, он, возможно, не исследовал другие пути к этому узлу назначения. - person evenodd; 18.11.2014
comment
@evenodd в этом прелесть TS -> если вы достигнете конечного пути, все вершины будут в прямом направлении. Таким образом, все узлы после пункта назначения не будут указывать на пункт назначения. - person Mitesh Pathak; 18.11.2014
comment
@MiteshPathak Да, но возможно, что у двух есть два разных пути к целевому узлу, верно? - person evenodd; 18.11.2014
comment
@evenodd Ага. Но все пути будут иметь узлы, которые находятся перед пунктом назначения в порядке TS. Пути от узлов после пункта назначения не существует, поскольку в TS нет заднего края. Попробуйте на примере, и вы поймете, о чем я говорю :) - person Mitesh Pathak; 18.11.2014
comment
Давайте продолжим обсуждение в чате. - person evenodd; 18.11.2014