2016-01-26 3 views
2

Мне дается ориентированный граф с весами, назначенными вершинам, а не ребрам. Моя цель - найти максимальный вес пути в этом графе. Вес пути - это сумма весов всех уникальных найденных в нем вершин. Вершину можно посещать несколько раз по пути, хотя она считается только один раз.Максимальная сумма уникальных весов вершин в графе

Циклы могут и, вероятно, будут присутствовать.

Веса положительные целые числа.

Реконструкция пути не требуется.

Из-за размера графика он не может быть представлен как матрица смежности (это может повлиять на временную сложность).

Граф не должен быть ни сильным, ни слабосвязанным.

Пример:

1 -> 20 -> 5 A | | \/ 14 <- 33 Лучший путь будет 1 -> 20 -> 33 -> 14 -> 1 -> 20 -> 5 с суммой 73.

+0

и в чем вопрос и что вы достигли до сих пор? – mikus

+0

@mikus Вопрос в том, как это можно сделать в сложное время. На данный момент я совершенно не знаю, и я понятия не имею, как подойти к этой проблеме. – Andrew

ответ

2

Шаг первый: устранить все циклы. Вы можете найти цикл, выбрав любой узел и сделав DFS. Если вы не найдете цикл, найдите другой узел, который вы не видели в предыдущей DFS, и выполните DFS с этого узла. Если вы обнаружите, что цикл сворачивает все узлы в один. В основном, если вы достигнете любого из узлов цикла, вы пройдете цикл, чтобы получить все веса. Поскольку вы можете повторно использовать узлы и края, вы всегда сможете продолжить свой путь по-прежнему. После того, как вы нашли цикл, повторите алгоритм, пока вы не свернете все циклы.

Шаг второй: найдите путь через свернутый граф. Теперь нет циклов, поэтому вы можете использовать Bellman Ford и найти самый длинный маршрут (вам нужно изменить условия, чтобы искать более длинные пути вместо более коротких). Поскольку каждый свернутый узел имеет весовой коэффициент цикла, который он представляет, вы получаете вес, который вы ищете. Если вы хотите восстановить путь, вам также нужно посмотреть на свернутые циклы и развернуть их на месте, позаботясь о добавлении пути из входной точки в точку выхода в цикле (скажем, у вас есть цикл с 10 узлами , край ввода переходит к узлу 1, но край выхода идет от узла 5, поэтому вам нужно добавить весь цикл 1,2,3,4,5 .. 10, начиная с входного края, а затем добавить часть цикла что приведет вас к краю выхода, в данном случае 1,2,3,4,5).

Сложность - O (N^2). DFS - это O (N) (включая выбор других узлов в случае, если вы не найдете их из текущего), и каждый раз, когда вы удаляете хотя бы один узел (вы не можете иметь цикл с одним узлом), поэтому вы будете запускать это не более N раз. Алгоритм BellmanFord также O (N^2). Реконструкция должна быть не более O (N).

+0

Большое спасибо. Поскольку веса представляют собой целые положительные числа (о которых я не упоминал ранее), алгоритм Дейкстры может быть использован вместо BF, что немного уменьшает сложность. Я немного напуган «O (N^2)» - может быть целых 200 000 вершин (и до 1 000 000 ребер). Я не уверен, что этот алгоритм будет соответствовать требованиям времени. – Andrew

+0

Я не думаю, что вы можете использовать Dijkstra, потому что вы ищете самый длинный путь (эквивалентный всем весам здесь отрицательный). Вы можете немного ускорить его, пытаясь быстрее свернуть циклы.Вы можете сделать это, запустив другую DFS из одного из узлов цикла, но перейдя по краям, а затем свернув все узлы, которые посетили обе DFS. Должно быть гарантировано максимальное количество узлов, которые вы обрушиваете сразу, но сложность остается примерно одинаковой. – Sorin

Смежные вопросы