Наблюдение: для каждого узла мы можем повторно использовать его минимальный путь к месту назначения, поэтому нам не нужно его пересчитывать (dp). Кроме того, как только мы обнаруживаем цикл, мы проверяем, отрицательный ли он. Если это не так, это не повлияет на наш окончательный ответ, и мы можем сказать, что он не подключен к месту назначения (независимо от того, подключен он или нет).
Псевдокод:
-
Указаны исходный узел u и целевой узел v
Инициализировать целочисленный массив dp, в котором хранится минимальное расстояние до конечного узла относительно исходного узла. dp [v] = 0, все остальное бесконечно
Инициализировать логический массив onPath, в котором хранится, находится ли текущий узел на рассматриваемом нами пути.
Инициализировать логический массив посещений, который отслеживает, был ли пройден текущий путь (изначально все ложно)
Инициализировать предварительный массив int, который хранит предварительное значение узла. (предварительный [u] = 0)
функция возврата (u).
int function(int node){
onPath[node] = true;
for each connection u of node{
if(onPath[u]){ //we've found a cycle
if(cost to u + tentative[node] > tentative[u]) //report negative cycle
continue; //safely ignore
}
if(visited[u]){
dp[node] = min(dp[node], dp[u]); //dp already calculated
}else{
tentative[u] = tentative[node] + cost to u
dp[node] = min(function(u), dp[node])
}
visited[node] = true;
onPath[node] = false;
return dp[node];
}
Я знаю, что этот алгоритм не будет охватить случай, когда пункт назначения является частью отрицательного цикла, но, кроме того, что-то не так с алгоритмом? Если нет, как это называется?