Алгоритм, який знаходить кількість простих шляхів від


34

Чи можна запропонувати мені алгоритм лінійного часу , який приймає в якості вхідних даних орієнтованого ациклического граф , і дві вершини і і повертає число простих шляхів від до в . У мене є алгоритм, в якому я буду запускати DFS (глибокий перший пошук), але якщо DFS знайде він не змінить колір (від білого до сірого) будь-якого з вузлів, що потрапляє в шлях так що якщо це підпуть будь-який інший шлях, то також DFS знову проходить цей підпуть. Для прикладу розглянемо список суміжності, де нам потрібно знайти кількість шляхів від p до v .G=(V,E)ststG
tstpv

poszorsvsrryyvvwzwz
Тут DFS почнеться з p а потім скаже, що він переходить до pz оскільки він не зустрічається v DFS буде працювати нормально. Тепер секунда шлях є psryv оскільки він зустрічається v ми не будемо змінювати колір вершин s,r,y,v на сірий. Потім шлях pov оскільки колір v все ще є білим. Потім шлях posryv,posryv оскільки колір s білий і аналогічно шлях poryv.Также підтримується лічильник, який збільшується, коли виникає v .

Чи правильний мій алгоритм? якщо ні, то які модифікації потрібні для виправлення чи будь-які інші підходи, будуть дуже вдячні.

Примітка . Тут я розглянув алгоритм DFS, який наведений у книзі "Введення в алгоритми Кормен", в якій він забарвлює вузли відповідно до їх стану. Отже, якщо вузол невідомий, не досліджений і досліджений, то колір буде білим, сірий і чорний відповідно. Всі інші речі є стандартними.



4
Зауважте, що всі шляхи в спрямованому ациклічному графіку обов'язково прості (в силу ациклічності).
Нолдорін

Відповіді:


37

Ваша поточна реалізація обчислить правильну кількість шляхів у DAG. Однак, не маркуючи шляхи, це займе експоненціальний час. Наприклад, на ілюстрації нижче, кожен етап DAG збільшує загальну кількість шляхів у кратне 3. Це експоненціальне зростання можна впоратися з динамічним програмуванням.

даг

Обчислення кількості - шляхів у DAG задається повторенням, st

Paths(u)={1if u=t(u,v)EPaths(v)otherwise.

Проста модифікація DFS обчислить це, задане як

def dfs(u, t):
    if u == t:
        return 1
    else:
        if not u.npaths:
            # assume sum returns 0 if u has no children
            u.npaths = sum(dfs(c, t) for c in u.children)
        return u.npaths

Не важко помітити, що кожен край дивиться лише один раз, звідси час виконання .О(V+Е)


Я зрозумів ваш алгоритм, і його можна зробити малоефективнішим, використовуючи динамічне програмування, оскільки одні й ті ж рекурсивні дзвінки викликаються багато разів, тому його краще зберегти. Право ??
Саураб

1
@SaurabhHota, він використовує динамічне програмування. Перший раз, коли зустрічається вершина , вона обчислює кількість шляхів, які вона має до . Це зберігається в u.npaths. Кожен наступний виклик не перерахує його кількість шляхів, а просто поверне u.npaths. уту
Ніколас Манкузо

1
Для таких графіків не є лише відповідь m ^ n, де m - кількість вузлів у стовпці (3 тут) і n - кількість стовпців, виключаючи s, t (4 тут). вихід 3 3 4 = 81 для прикладу графіка.
saadtaame

@saadtaame, звичайно; однак, моя мета полягала в тому, щоб просто продемонструвати експоненціальне збільшення у міру зростання "довжини" графіка. Звичайно, для цього високоструктурованого графіка ви можете рахувати у закритому вигляді, тоді як алгоритм, що перерахований, працює для всіх графіків.
Ніколас Манкузо

3
Час запуску передбачає, що ви можете виконувати необхідні доповнення в постійний час, але додані числа можуть мати біти в гіршому випадку. Якщо ви хочете визначити точну кількість контурів, час роботи (підрахунок бітових операцій) насправді є . Θ ( V ) O ( V E )O(V+E)Θ(V)O(VE)
JeffE

15

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

Тепер, якщо ви зберігаєте кількість шляхів від одного вузла до цілі під час відвідування вузлів, часова складність стає лінійною в кількості вершин і лінійною пам’яттю в кількості вузлів.


0

Кількість шляхів між будь-якими двома вершинами в DAG можна знайти, використовуючи матричне подання суміжності.

Припустимо, A - матриця примикання G. Прийнявши Kth потужність A після додавання до нього матриці ідентичності, дає кількість шляхів довжиною <= K.

Оскільки максимальна довжина будь-якого простого шляху в DAG дорівнює | V | -1, обчислення | V | -1-ї потужності дасть кількість шляхів між усіма парами вершин.

Обчислення | V | -1-ї потужності можна зробити, зробивши log (| V | -1) муліплікації кожного з TC: | V | ^ 2.


Питання задає лінійний алгоритм часу. Ваш алгоритм повільніше, ніж це.
DW

@Vivek Ви можете згадати посилання на теореми у своїй відповіді?
Хаміде
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.