Головна Мережі та Теорія графів Флойд-Уоршелл — найкоротші шляхи між усіма парами

🗺️ Флойд-Уоршелл — найкоротші шляхи між усіма парами

Флойд-Уоршелл знаходить найкоротші шляхи між кожною парою вершин за O(V³), релаксуючи через кожен проміжний вузол. Дивіться, як матриця відстаней стискається з просуванням опорного k.

Мережі та Теорія графів2DСередній60 FPS
floyd-warshall ↗ Відкрити окремо
DRAG · SCROLL · CLICK — керуйте прямо у вікні симуляції.

Про цю симуляцію

Ця симуляція виконує алгоритм Флойда-Уоршелла наживо на невеликому випадковому орієнтованому графі з 5–7 вершинами. Вона заповнює матрицю відстаней V×V, релаксуючи кожну пару (i, j) через опорну вершину k, по одному кроку потрійного циклу за раз, і підсвічує кожну клітинку в момент її покращення. Коли опорна вершина пройде через усі вершини, найкоротший шлях між обраними джерелом і ціллю підсвічується прямо на графі, відновлений з матриці наступного переходу, побудованої паралельно з відстанями.

🔬 Що показано

Зважений орієнтований граф (з'єднане кільце плюс кілька додаткових випадкових ребер), намальований у вигляді стрілок з вагами, поруч із живою матрицею відстаней V×V. У міру просування опорної вершини k підсвічуються її рядок і стовпець, будь-яка релаксована клітинка спалахує, а коли виконання завершується, ребра, що належать найкоротшому шляху джерело→ціль, стають фіолетовими, а показник відстані відображає підсумкову суму.

🎮 Як користуватись

Задайте кількість вершин (5–7) і швидкість, потім натисніть «Відтворити», щоб автоматично анімувати потрійний цикл, або «Крок», щоб просунутися рівно на одну опорну вершину k за раз. Оберіть джерело й ціль зі спадних списків, щоб визначити, який найкоротший шлях буде простежено після завершення алгоритму, і скористайтеся «Регенерувати» для нового випадкового графа. Панель журналу перелічує кожну релаксацію в міру її виконання у форматі k=X: A→B = нова відстань.

💡 Чи знали ви?

Флойд-Уоршелл не потребує черги з пріоритетами і перезапуску для кожного джерела — три звичайні вкладені цикли по всіх вершинах розв'язують усі пари одразу. Саме через цю плоску вартість O(V³) з малим сталим множником алгоритм часто є практичним вибором для малих або щільних графів, навіть попри існування асимптотично розумніших підходів для великих розріджених графів.

Часті питання

Що насправді контролюють повзунки «Вершини» та «Швидкість»?

Повзунок «Вершини» (від 5 до 7) визначає кількість вузлів у випадковому графі, що також задає розмір матриці відстаней і кількість опорних вершин, через які пройде алгоритм. «Швидкість» (від 0,2 до 4) керує тим, наскільки швидко «Відтворити» автоматично просувається через кроки релаксації; вона не впливає на «Крок», який завжди виконує релаксації рівно для однієї опорної вершини за клік.

Що відбувається, коли я натискаю «Відтворити» проти «Крок»?

«Відтворити» запускає алгоритм безперервно з обраною швидкістю, просуваючи i, j і врешті-решт опорну вершину k, поки всі опорні вершини не будуть оброблені й виконання не позначиться як «Завершено». «Крок» натомість просувається через одну цілу опорну вершину k за один клік, застосовуючи всі її релаксації (i, j) одразу, що корисно для паузи й огляду матриці між опорними вершинами.

Як обирається й малюється підсвічений найкоротший шлях?

Ви обираєте джерело й ціль зі спадних списків. Коли виконання завершується, симуляція відновлює шлях, слідуючи матрицею наступного переходу від джерела до досягнення цілі, і малює кожне ребро цього маршруту фіолетовим кольором на графі, а показник «Відстань шляху» відображає загальну вагу або символ нескінченності, якщо шляху не існує.

Чому деякі клітинки матриці відстаней показують символ нескінченності?

Символ нескінченності означає, що шлях між вершинами відповідного рядка та стовпця ще не знайдено. Діагональ завжди починається з 0, оскільки кожна вершина досягає самої себе з нульовою вартістю. У міру просування опорної вершини k через релаксації, значення нескінченності перетворюються на скінченні числа щоразу, коли k виявляється придатною проміжною ланкою між двома вершинами, які не були з'єднані напряму.

Чому граф генерується заново з різними ребрами щоразу?

«Регенерувати» будує новий випадковий орієнтований граф: з'єднане кільце, щоб кожна вершина могла досягти наступної, плюс кілька додаткових випадкових ребер з вагами від 1 до 9, тож форма задачі змінюється щоразу. Зміна повзунка «Вершини» також запускає повну регенерацію, оскільки розмір матриці та довжина кільця залежать від кількості вершин.

Часті питання про теорію

Що обчислює алгоритм Флойда-Уоршелла?

Флойд-Уоршелл обчислює найкоротший шлях між кожною парою вершин у зваженому графі одразу. Замість запуску алгоритму з одним джерелом для кожного вузла, він заповнює матрицю відстаней V×V, де dist[i][j] — довжина найкоротшого шляху від i до j. Він працює на орієнтованих і неорієнтованих графах та обробляє негативні ваги ребер, якщо немає негативного циклу.

Як працює релаксація через опорну вершину?

Алгоритм використовує потрійний цикл із зовнішньою опорною вершиною k. Для кожної пари (i, j) він перевіряє, чи шлях від i до k, а потім від k до j, коротший за поточний найкращий: dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]). Коли опорна вершина пройде через усі вершини, знайдено кожен найкоротший шлях, що використовує лише проміжні вершини з повної множини.

Чому Флойд-Уоршелл має складність O(V³)?

Є три вкладені цикли, кожен з яких проходить по всіх V вершинах: опорна вершина k, джерело i та ціль j. Це дає V × V × V = V³ кроків релаксації, тож часова складність становить O(V³). Просторова складність — O(V²) для матриці відстаней, плюс ще O(V²), якщо зберігати матрицю попередників для відновлення шляху.

Чому порядок динамічного програмування є коректним?

Після ітерації k значення dist[i][j] містить найкоротший шлях від i до j, якому дозволено проходити лише через проміжні вершини з номерами 1..k. Оскільки опорна вершина k є найзовнішнішим циклом, на момент використання dist[i][k] і dist[k][j] вони вже враховують усі попередні опорні вершини, тож рекурентне співвідношення завжди будується на оптимальних підрозв'язках. Це класичний інваріант динамічного програмування, який робить алгоритм коректним.

Як Флойд-Уоршелл обробляє негативні ребра та негативні цикли?

На відміну від Дейкстри, Флойд-Уоршелл допускає негативні ваги ребер і все одно повертає коректні найкоротші шляхи. Однак негативний цикл означає, що деякі найкоротші шляхи не визначені, оскільки можна нескінченно зменшувати вартість, проходячи циклом. Негативний цикл можна виявити після виконання: якщо будь-яке діагональне значення dist[i][i] стає негативним, вершина i лежить на негативному циклі. Ця симуляція використовує лише невід'ємні ваги, щоб результати були коректно визначені.

Як відновлюється найкоротший шлях?

Під час ініціалізації матриця наступного переходу next[i][j] встановлюється рівною j, коли існує пряме ребро. Щоразу, коли релаксація через опорну вершину k покращує dist[i][j], копіюється next[i][j] = next[i][k], фіксуючи, що найкращий маршрут тепер починається з напрямку до k. Щоб відновити шлях, потрібно слідувати за next[i][j] від джерела до досягнення цілі, збираючи вершини по дорозі.

Як Флойд-Уоршелл порівнюється з Дейкстрою?

Дейкстра розв'язує задачу найкоротшого шляху з одним джерелом і швидко працює на розріджених графах, але вимагає невід'ємних ваг і дає шляхи лише від одного джерела. Запуск Дейкстри з кожної вершини коштує приблизно O(V·E·log V) із купою, що перевершує Флойда-Уоршелла на великих розріджених графах. Флойд-Уоршелл із його плоскою вартістю O(V³) та малими сталими множниками простіший у реалізації й часто виграє на малих або щільних графах, коли справді потрібні всі пари.

Як він порівнюється з Беллманом-Фордом?

Беллман-Форд також працює з одним джерелом, але, як і Флойд-Уоршелл, допускає негативні ребра й може виявляти негативні цикли. Він працює за O(V·E) на одне джерело. Якщо потрібні найкоротші шляхи з одного джерела в графі з негативними ребрами, природним вибором є Беллман-Форд; якщо потрібні всі пари одразу, три компактні цикли Флойда-Уоршелла зазвичай простіші й конкурентоспроможні на щільних графах.

Що означає ∞ (INF) у матриці відстаней?

Значення ∞ означає, що наразі не відомий жоден шлях між цими двома вершинами. Діагональ dist[i][i] починається з 0, оскільки відстань від вершини до самої себе дорівнює нулю. У міру просування опорної вершини значення ∞ можуть ставати скінченними, коли проміжна вершина з'єднує два раніше незв'язані вузли — саме це «стискання» матриці ви бачите в анімації.

Де Флойд-Уоршелл використовується на практиці?

Він використовується для таблиць маршрутизації в невеликих мережах, обчислення транзитивного замикання відношення, знаходження діаметра й центральності графа, а також для розв'язання запитів про відстані між усіма парами в картах, іграх та дослідженні операцій. Булевий варіант обчислює досяжність, а варіант max-min розв'язує задачі найширшого шляху або вузького місця, замінюючи операції min/plus на max/min.

Схожі симуляції