Хтось може мені сказати, чому алгоритм Діккстри для найкоротшого шляху з одним джерелом передбачає, що краї повинні бути негативними.
Я говорю лише про ребра, а не про негативні цикли ваги.
Хтось може мені сказати, чому алгоритм Діккстри для найкоротшого шляху з одним джерелом передбачає, що краї повинні бути негативними.
Я говорю лише про ребра, а не про негативні цикли ваги.
Відповіді:
Нагадаємо, що в алгоритмі Дейкстри, коли вершина позначена як "закрита" (і поза відкритим набором) - алгоритм знайшов найкоротший шлях до нього , і йому більше ніколи не доведеться розвивати цей вузол - він передбачає шлях, розроблений до цього шлях найкоротший.
Але з негативними вагами - це може бути неправдою. Наприклад:
A
/ \
/ \
/ \
5 2
/ \
B--(-10)-->C
V={A,B,C} ; E = {(A,C,2), (A,B,5), (B,C,-10)}
Дайкстра з А спочатку розвине С, а згодом не зможе його знайти A->B->C
РЕДАКТУЙТЕ трохи глибше пояснення:
Зауважте, що це важливо, тому що на кожному кроці розслаблення алгоритм передбачає, що "вартість" для "закритих" вузлів дійсно мінімальна, і, таким чином, вузол, який буде обраний далі, також мінімальний.
Ідея його така: Якщо у нас вершина відкрита таким, що її вартість мінімальна - додаючи будь-яке додатне число до будь-якої вершини - мінімальність ніколи не зміниться.
Без обмеження на додатні числа - вищенаведене припущення не відповідає дійсності.
Оскільки ми «знаємо», що кожна вершина, яка була «закрита», мінімальна - ми можемо сміливо робити крок розслаблення - не «озираючись». Якщо нам потрібно "озирнутися назад" - Bellman-Ford пропонує рекурсивне (DP) рішення зробити це.
A->B
буде 5 і A->C
буде 2. Потім B->C
буде -5
. Значить, значення C
буде таким -5
же, як і bellman-ford. Як це не дає правильної відповіді?
A
зі значенням 0. Потім він подивиться на вузол з мінімальним значенням, який B
дорівнює 5 і C
дорівнює 2. Мінімальний - C
значить, він закриється C
зі значенням 2 і ніколи не оглянеться назад, коли пізніше B
закрито, воно не може змінити значення C
, оскільки воно вже "закрите".
A -> B -> C
? Спочатку оновиться C
відстань до 2, а потім B
відстань до 5. Припускаючи, що у вашому графіку немає вихідних країв C
, тоді ми нічого не робимо під час відвідування C
(а його відстань досі 2). Потім ми відвідуємо D
сусідні вузли, і єдиний сусідній вузол C
, нове відстань якого становить -5. Зауважте, що в алгоритмі Dijkstra ми також відслідковуємо батько, від якого ми C
дістаємось (і оновлюємо) вузол, і виконуючи це , ви отримаєте батьківський B
, а потім A
, що призводить до правильного результату. Що я пропускаю?
Коли в своєму поясненні я посилаюсь на алгоритм Дейкстри, я буду говорити про алгоритм Дейкстри, як реалізовано нижче,
Отже, починаючи значення ( відстань від джерела до вершини ), спочатку присвоєні кожній вершині,
Спочатку витягуємо вершину в Q = [A, B, C], яка має найменше значення, тобто A, після чого Q = [B, C] . Примітка A має спрямований край до B і C, і обидва вони знаходяться в Q, тому ми оновлюємо обидва ці значення,
Тепер витягуємо C як (2 <5), тепер Q = [B] . Зауважте, що C пов'язаний ні з чим, тому line16
цикл не працює.
Нарешті витягуємо В, після чого . Примітка B має спрямований край до C, але C відсутня в Q, тому ми знову не вводимо цикл for line16
,
Отже, ми закінчуємо відстані як
Зверніть увагу, як це неправильно, оскільки найкоротша відстань від А до С становить 5 + -10 = -5, коли ви йдете .
Тож для цього графіка Алгоритм Дійкстри неправильно обчислює відстань від А до С.
Це відбувається тому , що алгоритм Дейкстри не намагається знайти більш короткий шлях до вершин , які вже витягнутими з Q .
Що line16
робить цикл, це взяти вершину u і сказати: "Ей, схоже, ми можемо перейти до v від джерела через u , це те, що (альт або альтернатива) відстань краще, ніж поточний dist [v], який ми отримали? Якщо так, можна оновити dist [v] "
Зверніть увагу , що в line16
вони перевіряють всі сусіди V (тобто спрямоване ребро існує від U до V ), з U які ще в Q . У line14
них видалити відвідану замітку з Q. Таким чином , якщо х є відвідуваним сусідом U , шлях буде навіть не розглядаються як можливий короткий шлях від джерела до V .
У нашому прикладі вище C був відвідуваним сусідом B, тому шлях не вважався, залишаючи поточний найкоротший шлях незмінним.
Це насправді корисно, якщо ваги краю - це позитивні цифри , тому що тоді ми б не витрачали час на розгляд шляхів, які не можуть бути коротшими.
Тому я кажу, що при запуску цього алгоритму, якщо x витягується з Q до y , то не можна знайти шлях - який коротший. Дозвольте пояснити це на прикладі,
Оскільки y щойно був видобутий і x був видобутий раніше, тоді dist [y]> dist [x], оскільки в іншому випадку y був би вилучений до x . ( line 13
хв відстань спочатку)
І як ми вже припускали, що крайові ваги позитивні, тобто довжина (x, y)> 0 . Таким чином, альтернативна відстань (alt) через y завжди впевнено більша, тобто dist [y] + довжина (x, y)> dist [x] . Таким чином, значення dist [x] не було б оновлене, навіть якби y розглядалося як шлях до x , тож ми робимо висновок, що має сенс розглядати лише сусідів y, які ще перебувають у Q (зверніть увагу на line16
)
Але ця річ залежить від нашого припущення про позитивну довжину ребра, якщо довжина (u, v) <0, то залежно від того, наскільки негативним є цей край, ми можемо замінити dist [x] після порівняння в line18
.
Отже, будь-який розрахунок dist [x], який ми робимо, буде невірним, якщо x буде видалено до того, як всі вершини v - такі, що x - сусід v з негативним ребром, що з'єднує їх, - буде видалено.
Оскільки кожен з цих v вершин є другою останньої вершиною на потенціалі «кращого» шлях від джерела до й , який відкидається алгоритмом Дейкстри.
Отже, у прикладі, який я наводив вище, помилка полягала в тому, що C було видалено до видалення B. Поки той С був сусідом Б з негативним краєм!
Просто для уточнення, B і C - сусіди А. B має одного сусіда C, а C не має сусідів. довжина (a, b) - довжина ребра між вершинами a і b.
Алгоритм Дейкстри передбачає, що шляхи можуть стати лише "важчішими", так що якщо у вас є шлях від А до В з вагою 3 і шлях від А до С із вагою 3, ви не можете додати край і дістатися від А до В до С із вагою менше 3.
Це припущення робить алгоритм швидшим, ніж алгоритми, які повинні враховувати негативні ваги.
Правильність алгоритму Дейкстри:
У нас є 2 набори вершин на будь-якому кроці алгоритму. Множина A складається з вершин, до яких ми обчислили найкоротші шляхи. Множина B складається з вершин, що залишилися.
Індуктивна гіпотеза : На кожному кроці ми будемо вважати, що всі попередні ітерації є правильними.
Індуктивний крок : Коли ми додамо вершину V до множини A і встановимо відстань, яка має бути віддаленою [V], ми повинні довести, що ця відстань є оптимальною. Якщо це не є оптимальним, до вершини V має бути якийсь менший шлях.
Припустимо, це якийсь інший шлях проходить через деяку вершину X.
Тепер, оскільки dist [V] <= dist [X], тому будь-який інший шлях до V буде найменшою довжиною dist [V], якщо граф не має від'ємної довжини ребра.
Таким чином, для роботи алгоритму диккстри ваги ребер повинні бути негативними.
Спробуйте алгоритм Діккстри на наступному графіку, припустивши, що A
це вихідний вузол, щоб побачити, що відбувається:
A->B
воля 1
і A->C
воля 100
. Тоді B->D
буде 2
. Тоді C->D
буде -4900
. Значить, значення D
буде таким -4900
же, як і bellman-ford. Як це не дає правильної відповіді?
A->B
буде 1
і A->C
буде 100
. Потім B
досліджується і налаштовується B->D
на 2
. Тоді D досліджується, оскільки в даний час він має найкоротший шлях до джерела? Чи був би я правильним, кажучи, що якби B->D
був 100
, C
то був би досліджений першим? Я розумію всі інші приклади, які наводять люди, крім вашого.
Нагадаємо, що в алгоритмі Дейкстри, коли вершина позначена як "закрита" (і поза відкритим набором) - вона передбачає, що будь-який вузол, що виходить з неї, призведе до більшої відстані , тому алгоритм знайшов найкоротший шлях до нього, і буде ніколи більше не потрібно розробляти цей вузол, але це не відповідає дійсності у випадку негативних ваг.
Інші відповіді поки що доволі добре демонструють, чому алгоритм Дейкстри не може впоратися з негативними вагами на трасах.
Але саме питання, можливо, засноване на неправильному розумінні ваги шляхів. Якщо б негативні ваги на шляхах були дозволені в алгоритмах прокладання маршрутів взагалі, ви отримаєте постійні петлі, які не зупиняться.
Врахуйте це:
A <- 5 -> B <- (-1) -> C <- 5 -> D
Який оптимальний шлях між A і D?
Будь-який алгоритм накладання маршрутів повинен постійно тримати цикл між B і C, оскільки це зменшить вагу загального шляху. Таким чином, якщо дозволити негативне зважування для з'єднання, буде відображено будь-який спір алгоритму pathfindig, можливо, за винятком випадків, коли ви обмежуєте використання кожного з'єднання лише один раз.
Ви можете використовувати алгоритм dijkstra з негативними ребрами, не включаючи негативний цикл, але ви повинні дозволити, що вершину можна буде відвідувати кілька разів, і ця версія втратить її швидкість у часі.
У цьому випадку практично я бачив, що краще використовувати алгоритм SPFA, який має нормальну чергу і може обробляти негативні краї.