Чи є транзитивним зниженням DAG?


11

Мета цього завдання задається кінцево спрямованим ациклічним графіком (DAG), визначають, чи є графік транзитивним скороченням .

Коротке пояснення, що таке DAG та перехідні скорочення:

DAG - це графік із спрямованими ребрами (тобто ви можете рухатись лише в одному напрямку на цьому краї) таким чином, що з урахуванням будь-якого початкового вузла на графіку неможливо повернутися до початкового вузла (тобто циклів немає).

З огляду на будь-який початковий вузол, якщо є можливість перейти до іншого кінцевого вузла в графіку через будь-яке довільне додатне число ребер, то цей кінцевий вузол визначається як доступний із початкового вузла. У загальній DAG може бути кілька шляхів, які можна пройти від стартового вузла до цільового кінцевого вузла. Наприклад, візьміть цей алмазний графік:

введіть тут опис зображення

Щоб дістатися до вузла Dз A, ви могли б піти по шляху A->B->Dабо A->C->D. Таким чином, Dдоступний від A. Однак немає шляху, який можна пройти, щоб дістатися до вузла, Bпочинаючи з вузла C. Таким чином, вузол Bнедоступний від вузла C.

Визначення досяжності графа в вигляді списку досяжних вузлів для кожного початкового вузла в графі. Отже, для того ж прикладу алмазного графіка доступність:

A: [B, C, D]
B: [D]
C: [D]
D: []

Інший графік, який має таку ж доступність, як і вищенаведений графік, показаний нижче:

введіть тут опис зображення

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

Для кінцевої DAG перехідне зменшення гарантовано існує і є унікальним.

Вхідні дані

Вхід - це "список списків", де зовнішній список має довжину кількості вершин, а кожен внутрішній список - це довжина кількості ребер, що залишають пов'язаний вузол, і містить показники вузлів призначення. Наприклад, одним із способів описати перший графік був би (якщо припустити нульову індексацію):

[[1, 2], [3], [3], []]

Ви можете почати індексацію першого вузла при будь-якому довільному цілому значенні (наприклад, 0 або 1 на основі індексації).

Вхід може надходити з будь-якого потрібного джерела введення (stdio, параметр функції тощо). Ви можете вибрати точний формат вводу до тих пір, поки додаткова інформація не буде надана. Наприклад, якщо ви хочете взяти вхід з stdio, у кожного рядка може бути список ребер для пов'язаного вузла. Наприклад:

1 2
3
3
'' (blank line)

Індекси у кожному списку суміжності не обов'язково сортуються, і може бути кілька ребер, що з'єднують два вузли (напр .:) [[1,1],[]]. Ви можете припустити, що графік введення слабко пов'язаний і не містить циклів (тобто це DAG).

Вихідні дані

Вихід є правдивим, якщо заданий вхідний DAG є транзитивним зменшенням, а помилковим значенням є інше. Це може бути будь-яка потрібна раковина (stdio, значення повернення, вихідний параметр тощо)

Приклади

У всіх прикладах використовується індексація на основі 0.

[[1,2],[3],[3],[]]
true

[[1,2,3],[3],[3],[]]
false

[[1,1],[]]
false

[[1,2,3,4],[5,6,7],[5,8,9],[6,8,10],[7,9,10],[11,12],[11,13],[12,13],[11,14],[12,14],[13,14],[],[],[],[]]
true

[[5,6,7],[2,3,0,4],[5,8,9],[6,8,10],[7,9,10],[11,12],[11,13],[12,13],[11,14],[12,14],[13,14],[],[],[],[]]
true

[[5,6,7],[2,3,0,4,14,5,7],[5,8,9],[6,8,10],[7,9,10],[11,12],[11,13],[12,13],[11,14],[12,14],[13,14],[],[],[],[]]
false

[[5,6,7],[2,3,0,4],[5,8,9],[6,8,10],[7,9,10,14],[11,12],[11,13],[12,13],[11,14],[12,14],[13,14],[],[],[],[]]
false

[[1,3],[2],[3],[]]
false

Оцінка балів

Це код гольфу; виграє найменший код у байтах. Ваш код повинен заповнитися за розумну кількість часу (максимум 10 хвилин на будь-якому обладнання). Застосовуються стандартні лазівки. Ви можете використовувати будь-які бажані вбудовані модулі.


Чи можемо ми зробити будь-які припущення щодо підключення вводу? (Я не перевірив усі ваші тестові випадки, але чи охоплюють вони декілька роз'єднаних частин графіка?)
Мартін Ендер,

оновлено те, що я вважаю правильною мовою.
helloworld922

Я думаю, це добре. Можна також сказати, що графік слабко пов'язаний .
Мартін Ендер

Відповіді:


5

Рубі, 101 97 байт

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

Спробуйте в Інтернеті!

->g{r=->i{i|i.map{|j|r[g[j]||[]]}.inject([],:|)}
g.all?{|e|e==e&e&&e.none?{|i|r[e-[i]].index i}}}

4

Математика, 95 82 байт

13 байт збережено завдяки @MartinEnder .

#~IsomorphicGraphQ~TransitiveReductionGraph@#&@Graph[x=0;##&@@Thread[++x->#]&/@#]&

Анонімна функція. Приймає вкладений список як (на основі 1) введення та повертає Trueабо Falseяк вихід. Основне рішення тут - 46-байт #~IsomorphicGraphQ~TransitiveReductionGraph@#&, який перевіряє, чи заданий графік є ізоморфним для його транзитивного скорочення. Решта перетворює вхід на Graphоб’єкт.


3

CJam (41 байт)

q~:A_,{{Af=e__&}%_}*]:.|A.&A:$:e`e_2%1-*!

Інтернет демо , тестова

Розсічення

q~:A      e# Parse input and store in A
_,{       e# Loop V times
  {       e#   Extend adjacency list representation of G^i to G^(i+1)
    Af=   e#   by extending each path by one edge
    e__&  e#   and flattening. NB :| would be shorter but breaks for empty lists
  }%
  _       e#   Duplicate, so that we build up G^2, G^3, ..., G^n
}*]       e# Gather in a single array
:.|       e# Fold pointwise union, giving the reachability from each vertex by
          e# paths of length > 1
A.&       e# Pointwise intersect with the paths of length 1
          e# We hope to get an array of empty arrays

          e# Handle the awkward special case of duplicate edges:
A:$       e# Sort each adjacency list
:e`       e# Run-length encode each adjacency list
e_2%      e# Extract only the run lengths
1-        e# Discard the 1s - so we now have an empty array unless there's a dupe

*         e# Join. We hope to be joining an array of empty arrays by an empty array
          e# giving an empty array
!         e# Check that we get a falsy value (i.e. the empty array)

3

Желе, 20 байт

ị³$ÐĿ€ị@Fœ&¥";œ-Q$€E

Використовує індексацію на основі 1. Спробуйте в Інтернеті!

Розсипний огляд

     €                for each vertex,
ị³$ÐĿ                   compute its reach.
        Fœ&¥"         intersect each vertex's lists of children and
      ị@                children's reaches.
             ;        then concatenate the list of intersections with
              œ-Q$€     all duplicate edges in the original graph.
                   E  are all elements equal? checks that all are empty lists,
                        meaning empty intersections and no duplicates.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.