Алгоритм Цикла Отрицательного Веса

Я думал об алгоритме нахождения отрицательного весового цикла в направленном графе. Проблема в том,что у нас есть граф G(V, E), нам нужно найти эффективный алгоритм для поиска цикла с отрицательным весом. Я понимаю алгоритм в этом документе PDF

кратко, алгоритм применяет алгоритм Беллмана Форда, повторяя / V / -1 раз, делая релаксации. После этого он проверяет, есть ли край, который можно еще больше расслабить, а затем отрицательный вес цикл существует, и мы можем проследить его по родительским указателям, и все идет хорошо, мы находим отрицательный цикл веса.

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

мой алгоритм неправильный? Если да, то можете ли вы найти контрпример ? Если вы не можете помочь мне доказать это?

Спасибо

3 ответов


одна ясная проблема, вы отмечаете узлы.

 A <--->   B
 |         ^ 
   \--\    |  
           v    
       ->  D  (crap ascii art, A  connects to D unidirectionally)

Предположим, вы берете путь A->B - >D, A B D серые, когда вы нажмете D. цикл не найден. Вы выскакиваете на A; B и D черные. Вы берете край, цикл не найден, потому что D черный.

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


Bellman Ford не всегда работает, проблема в его один источник кратчайший путь алгоритм, если отрицательный цикл недоступен из источника, который вы выбираете, он терпит неудачу. Однако небольшое изменение в Bellman Ford может помочь, вместо выбора исходной вершины и инициализации ее расстояния до 0, мы можем инициализировать все расстояние до 0, а затем запустить Bellman Ford. Это эквивалентно добавлению дополнительной вершины s', которая указывает на все вершины исходного графа с 0 весом край. Как только Беллман Форд запускается на графике,и мы нашли любую вершину u и ребро (u, v), которые делают d[u] + w[u][v]

DFS не будет работать в любом случае, это, очевидно, не в состоянии исчерпать все возможные циклы. DFS можно использовать для поиска наличия цикла в графике, но не более.


Я верю, что есть способ решить это в линейном времени. При поиске графика с помощью функции "глубина-первый поиск" (DFS имеет время выполнения O (V+E)) вы можете отслеживать расстояние от источника до текущего узла (просто увеличивая расстояние родителя с весом ребра, соединяющего дочерний узел с родительским). Затем, всякий раз, когда вы сталкиваетесь с циклом (циклы обнаруживаются путем нахождения заднего края в неориентированном графе или либо заднего края, либо переднего края в направленном график), вы можете вычесть расстояние между исходным узлом и корневым узлом цикла от расстояния между исходным узлом и конечным узлом цикла (корневым узлом является узел, где цикл начался). Если результат отрицательный, цикл должен быть отрицательным!