You are on page 1of 27

Тема 3.

Алгоритми розв'язання проблем, сформульованих у термінах графів


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

Лекція 3.1. Базові поняття оцінки алгоритмів і їх застосування для обходу вершин
графу
У цій лекції розглянемо необхідні для оцінки трудомісткості алгоритмів означення і
продемонструємо їх для важливого класу алгоритмів пошуку в глибину.
1. Аналіз і оцінка алгоритмів . Будемо думати, що наша універсальна машина здатна
виконувати зазначену множину операцій.
2. Алгоритм пошуку в глибину і його оцінка. Нехай G - неорієнтований зв'язний граф.
У процесі пошуку в глибину вершинам графа G привласнюються номери (ПГ-номери), а його
ребра позначаються. На початку ребра не позначені, вершини не мають ПГ-номерів.
Починаємо з довільної вершини V0 . Приписуємо їй ПГ-номер ПГ(V0) = 1 і обираємо довільне
ребро V0W. Ребро V0W позначається як «пряме», а вершина w одержує (з V0) ПГ-номер ПГ(w) =
2. Після цього переходимо у вершину w. Нехай у результаті виконання декількох кроків
цього процесу прийшли у вершину х, і нехай k — останній привласнений ПГ-номер. Далі
діємо в залежності від ситуації в такий спосіб:
1. Маємо непозначене ребро ху. Якщо у вершини у уже є ПГ-номер, то ребро ху
позначаємо як «зворотнє» і продовжуємо пошук непозначеного ребра, інцидентного вершині
х. Якщо ж вершина в ПГ-номера не має, то нехай ПГ(y)=k+1, ребро ху помічаємо як «пряме»
і переходимо у вершину в. Вершина у вважається тією, що має свій ПГ-номер з вершини х.
На наступному кроці будемо переглядати ребра, інцидентні вершині в.
2. Усі ребра, інцидентні вершині х, позначені. У цьому випадку повертаємося у
вершину, з якої х одержала свій ПГ-номер.
Процес закінчиться, коли всі ребра будуть позначені і відбудеться повернення у
вершину V0.
Описаний процес можна реалізувати так, щоб час роботи відповідного алгоритму
складав 0(|EG|+|G|).
Такий алгоритм (алгоритм A1) ми зараз розглянемо. Нехай граф G заданий списками
суміжності, тобто Nv — список вершин, інцидентних вершині v, і V0 — вихідна вершина, з
яким починається пошук. У процесі роботи алгоритму кожна вершина графу лише один раз
включається в список Q і виключається з нього. Вершина включається в цей список відразу
після одержання ПГ-номера, і виключається, як тільки відбудеться повернення з цієї
вершини. Включення і виключення вершин починається завжди з кінця списку, тобто Q —
стек. Результат роботи алгоритму — чотири списки ПГ, F, Т і В:
ПГ(v) - ПГ-номер вершини v; F(v) - ім'я вершини, з якої вершина v одержала свій ПГ-
номер; Т і В — відповідно списки орієнтованих «прямих» і «зворотніх» ребер графа G. Ці
ребра одержують орієнтацію в процесі роботи алгоритму A1. Саме, якщо ребро ху
позначається з вершини х як «пряме», то в Т заноситься дуга (x, y), а як «зворотнє», то ця
дуга заноситься у В.
Алгоритм A1 пошуку в глибину в неорієнтованому зв'язному графі.
1. ПГ(V0):=1, Q(1):=V0, F(V0):=0, Т:=Ø,У:=Ø, k:=1, р:=1 [k - останній приписаний ПГ-
номер, р — покажчик кінця стека Q, тобто Q(p) - ім'я останньої вершини стека Q].
2. v := Q(p) [v — досліджувана вершина].
3. Переглядаючи список Nv знайти таку вершину w, що ребро vw не позначене, і
перейти до п. 4. Якщо таких вершин немає, то перейти до п. 5.
4. Якщо вершина w має ПГ-номер, то позначити ребро vw як «зворотнє» і занести дугу
(v,w) у список В. Перейти до п. 3 і продовжити перегляд списку Nv. Інакше k:=k+1,
ПГ(w):=k, F(w):=v, ребро vw позначити як «пряме» і дугу (v, w) занести в список Т, р:=р+1,
Q(p) := w [вершина w одержала ПГ-помер і занесена в стек Q]. Перейти до п. 2.
5. р:=р—1 [вершина v викреслена з Q ] Якщо р = 0, то кінець. Інакше перейти до п. 2.
Коректність алгоритму безперечна. Оцінимо його трудомісткість. Кожне включення і
виключення вершини зі стека Q виконується за час 0(1). Тому для всієї роботи, зв'язаної зі
зміною стека Q, достатньо часу 0(/G/). Кожне виконання п. 4 вимагає 0(1) часу, і для кожної
вершини v Є VG цей пункт виконується deg v раз. Тому витрати на його виконання в цілому
складуть ПРО( ∑ deg v) == 0(|EG|). Сумарний час
Виконання п.3 також складе 0(|EG|), якщо подбати про те, щоб кожна вершина списку
Nv розглядалася тільки один раз при всіх виконаннях цього пункту. Цього легко домогтися,
якщо, наприклад, увести таку нову функцію (масив) t, що t(v)-номер першої непереглянутої
вершини в списку Nv. Тоді наступний перегляд п.3 варто починати з вершини z =Nv(t(v)).
Отже, трудомісткість алгоритму A1 складає 0(|EG|+|G|). Зрозуміло, що цей час є
найкращим з можливих з множини, тому що кожна вершина і кожне ребро графа G повинні
бути переглянуті хоча б один раз.
Легко бачити, що необхідний для реалізації алгоритму A1 обсяг пам'яті також складає
0(|EG| + |G|).
На мал. 7 ліворуч зображені граф G і списки суміжності, якими він заданий. Праворуч
представлені результати застосування до цього графа пошуку в глибину з вершини vo=1.
1 1
N1 = (3,2,5)
2 N2=(4,1,5)
2 2
3 N3=(1,5)
4 5 N4=(2,5) 5
N5=(2,1,3,4,7,6) 3
6 N6=(5,7)
7
N7=(5,6) 6
7

Мал. 73.1
«Прямі» ребра проведені суцільними лініями, а «зворотні» пунктирними. Кожній
вершині приписаний її ПГ-номер.
Зі способу побудови безлічей Т и В безпосередньо випливають наступні твердження.
Твердження 73.1. Дуги безлічі Т утворять орієнтоване остовное дерево з коренем у
вершині vo.
Це остовне дерево часто називають остовне глибинне дерево (ОГД). Позначати його
будемо також через Т.
Твердження 73.2. Якщо орієнтоване ребро (х, у) належить У, то ПГ(x)> ПГ(y),
тобто «зворотні» ребра завжди ведуть до раніше пройдених вершин.
Пошук у глибину використовують як складену частину в багатьох алгоритмах.
Відзначимо одну задачу, розв’язок якої можна одержати за допомогою алгоритму A1 відразу,
майже без додаткових обчислювальних витрат. Це — задача виділення зв'язних компонентів
графа. Щоб вирішити її за час 0(|EG| + |G|), достатньо один раз переглянути список вершин
графа, виконуючи наступні дії. Якщо вершина, що переглядається, vl має Пг-номер, то
перейти до наступного. Інакше — покласти vo=vl, ПГ(vo)= k+1, де k — останній привласнений
ПГ-номер, і застосувати пошук у глибину. Після його закінчення (тобто виділення
компонента, що містить vl) продовжити перегляд списку, перейти до вершини vl+1. Розрізняти
вершини різних компонентів можна, наприклад, по їхній Пг-номерам, якщо для кожного
компонента запам'ятати останній Пг-номер.
Лекція 3.2. Алгоритми визначення двохзв’язних компонент і їх оцінка
У цій лекції ми розглянемо застосування пошуку в глибину до виділення двох
зв’язних компонентів графа. Тут справа обстоїть не так просто, як у попередній задачі.
Звичайно, можна було б, видаляючи по черзі вершини графа і щораз виділяючи зв'язкові
компоненти, знайти його точки зчленування і блоки. Такий підхід, однак, приводить до
алгоритму складності принаймні O(|G||EG|). Використання більш глибоких властивостей ПГ
дозволяє одержати лінійний по складності алгоритм розв’язку цієї задачі.
1. Дослідження властивостей алгоритму пошуку в глибину. Надалі зручно
використовувати наступні терміни. Нехай D = (V, A) – орієнтоване дерево, x, y V. Назвемо
x батьком вершини y, а y – сином вершини x, якщо дуга (x, y) належить А. Будемо говорити,
що вершини x і y порівнянні, якщо при цьому y досяжна з x. Якщо при цьому y досяжна з x,
то x – предок вершини y, а y – нащадок вершини x. Підграф графа D, породжений безліччю,
що складається з вершини y і всіх її нащадків, будемо позначати через Dy і називати
піддеревом з коренем y.
Нехай у графі G пророблений пошук у глибину з вершини v0 і отримане остовне
глибинне дерево Т і безліч компонентів.
Теорема 74.1. Якщо дуга (x, y) належить У, то x є нащадком вершини y у Т.
Доказ. Треба довести, що вершина x належить піддереву Ту. Припустимо противне.
Відповідно до твердження 73.2 вершина x одержує свій Пг-номер пізніше, ніж y. Тому
присвоєння вершині x Пг-номера відбудеться не раніш, ніж будуть відвідані усі вершини
дерева Ту і відбудеться повернення у вершину s = F(y). Але повернення в s не може
відбутися перш, ніж усі вершини безлічі Ny одержать Пг-номера. Оскільки xNy і ПГ-
номера до цього моменту не має, то одержуємо протиріччя.
наступні два твердження показують, яким чином пошук у глибину «реагує» на точки
зчленування графа.
Теорема 74.2. Вершина v0 є точкою зчленування графа G тоді і только тоді, коли
вона має не менш двох синів.
Доведення. Нехай v0 – точка зчленування графа G. Безперечно, що кожен блок графу,
що включає вершину v0 містить принаймні одного з її синів.
Нехай тепер s1, s2, ...,sk – сини вершини v0. Розглянемо піддерева.
Tsi (i  1, k ).
Безперечно, що
k
VG  v0  Vsi .
i 1

Для доведення незв’язності графу G - v0 досить показати, що в цьому графі немає


ребер, що зв'язують вершини різних Тsi. Але це відразу випливає з твердження 74.1. 
Будемо говорити, что x – власний предок (нащадок) вершини y, якщо x – предок
(нащадок) y і x  y.
Теорема 74.3. Вершина v  v0 є точкою зчленування графа G тоді і тільки тоді, коли
для деякого сина s цієї вершини не існує дуги (x, y) B такої,що x – нащадок (не обов'язково
власний) вершини s а y – власний предок вершини v.
Gi (i  2, m)
Доказ. Нехай v – точка зчленування графа G і G1 , G2 , ...,Gm, m  2, – блоки цього
графа, що містять вершину v. Нехай, далі, v = F(v), тобто v – батько вершини v. Не
втрачаючи спільності вважаємо, что вершина v міститься в блоці G1. Кожний з інших блоків
повинний, очевидно, містити хоча б одну вершину, що є сином вершини v. Нехай,
наприклад, s – син вершини v і s ( G2. Якщо тепер допустити існування «зворотнього» ребра
ab ( тобто дуги (a, b) ( У) такої, що а – нащадок s, а b – власний предок вершини v, то
прийдемо до існування в графі G простого циклу, що містить вершини s і v( належать
одному блоку. Одержали протиріччя.
Доведемо тепер другу частину твердження. Нехай вершина s є сином вершини v, для
якого виконується умова, що фігурує у формулюванні твердження. Ця умова разом із
твердженням 74.1 означає, що якщо ab – «зворотнє» ребро й а ( Тs, те або b ( Тs, або b = v.
Останнє означає, що всі ребра графа G, що зв'язують вершини безлічі Vтs, інцидентні
вершині v, тобто v – крапка зчленування графа G. 

v0
B1
C1 C2B3

B
4

B2

Мал. 74.1

c3

B6
c4 y

B7

Перейдемо тепер безпосередньо до розробки алгоритму виділення блоків графа.


2. Алгоритм виділення блоків графа. Щоб усвідомити схему застосування ПГ до
розв’язку цієї задачі, звернемося до прикладу. На мал. 74.1. зображений граф «з точністю до
блоків». ПГ починається у вершині v0. Після декількох кроків прийдемо в одну з точок
зчленування графа, наприклад, у з2. Нехай, далі, обирається і позначається як «пряме» ребро
c2x блоків У4. Після цього подальша робота ПГ аж до повернення в з2 відбувається точно
так, ніби було v0 = з2 і блоків У1, У2, У3 у графі G не було б зовсім. Тому повернення в з2
відбудеться пізніше, ніж повернення в з3 і з4 з висячих блоків У5, У6, У7. Ці розгляди
приводять до наступного важливого висновку. Найперше повернення в точку зчленування
відбудеться відразу ж після завершення обходу всіх ребер деякого висячого блоку Вк. Це ж
справедливо і стосовно подальшого поводження ПГ у графі, який отримано із графа G
видаленням блоку Вк.
Покажемо, як використовувати сказане вище в припущенні, якщо ми маємо спосіб, що
дозволяє при кожнім поверненні з вершини v у F(v) визначати, ли є F(v) точкою
зчленування. З цією метою заведемо стек S, у який будемо заносити всяке ребро графа G
відразу після одержання їм позначки “пряме” чи “зворотне”. Таким чином, усі ребра
додаються в кінець списку S. Нехай у нашому прикладі повернення з вершини y у c4 (див.
рис 74.1 ) є самим першим поверненням у крапку зчленування. Тоді до моменту повернення
в c4 ребра блоку В6 будуть займати всі t останніх місць у стеці S, де t - число ребер цього
блоку. Важливо при цьому, що ребро з4y займає перше серед t зазначених місць. Це
дозволяє, переглядаючи стек S зправа ліворуч, виділити (тобто , наприклад, перемістити в
окремий список) усі ребра блоку В6 . Потім ці ребра виводять з S.
Отже, з огляду на сказане, необхідно вміти в процесі ПГ швидко визначати
повернення у вершину, що є точкою зчленування. Твердження 74.2 і 74.3 дають відповідні
критерії, і нам треба их “алгоритмизивати”. З цією метою для кожної вершини v є VG
визначимо безліч P(v). У цю безліч включимо вершину v і кожного її предка w, для якого
існує “зворотнє” ребро xw таке, что х – нащадок вершини v в остовному глибинному дереві
Т. Іншими словами, безліч P(v) складається з усіх предків вершини v, яких можна досягти з v,
проходячи спочатку декілька (можливо, жодної) дуг дерева Т, а потім одну дугу безлічі В.
Уведемо тепер функцію l(v), v є VG, припускаючи l(v) = min ПГ(х) , х є P(v).
Наприклад у графі на мал. 73.1 l(1)=1, l(2)=1, l(3)=1, l(4)=3, l(5)=1, l(6)=3, l(7)=3.
Використовуючи функцію l(v), сформулюємо твердження 74.3 у наступному вигляді,
більш зручному для організації обчислень.
Теорема 74.4. Вершина v <> v0 є точкою зчленування графа G тоді і только тоді,
коли існує такий син s цієї вершини, что l(s)>= ПГ(v).
Обчислити значення л(в) неважко, якщо відомі значення функції л для всіх синів
вершини в. Саме, якщо S1, S2, ... , Sm – сини вершини в, то має місце формула
l(v) = min {{ l(S1) , l(S2) , ... , l(Sm), ПГ(v)} U {ПГ(w)| (v,w) є B }} (1)
Справедливість цього співвідношення стає очевидною якщо помітити наступне: Безліч
передків вершини v, досяжних з неї з використанням дуг дерева Т та не більш однієї дуги з
У, складається з предків v, досяжних такім самим шляхом з вершин S1, S2, ... , Sm, і безлічі
вершин, до яких ведуть зворотні ребра від вершини v.
Використовуючи співвідношення (1) , функцію l можна обчислювати разом з
виконанням звичайних операцій пошуку в глибину. При першому відвідуванні вершини v
разом із присвоєнням ПГ – номера думаємо l(v) = ПГ(v). Надалі це значення коректується
відповідно до формули (1) у такий спосіб. Усякий раз, коли відбувається повернення у
вершину v з деякого її сина s, думаємо l(v):= min {l(s),l(v)}. Крім того, коли деяке ребро vw
позначається як “зворотнє”, думаємо l(v):=min {l(v), ПГ(w)}. До моменту повернення з v у
вершину х = F(v) буде обчислене щире значення l(v) , що надалі використовується для
коректування l(х). Істотно, що кожне з цих коректувань вимагає тільки ПРО(1) додатковий
час. Тому ПГ разом з обчисленням функції l як і раніше буде виконуватися за час ПРО(|EG|
+|G|).
Ще одна добавка до “стандартного” пошуку в глибину пов'язана з точками
зчленування. Для виявлення точки зчленування досить після кожного повернення у вершину
в з деякого її сина порівняти величини l(s) і ПГ(v). Якщо виявиться, что l(s) >= ПГ(v), то всі
ребра стека S, починаючи з останнього і кінчаючи sv, віддаляються з цього списку. Вилучені
ребра складають один із блоків графа G. Відповідно до твердження 74.4 нерівність l(s) >=
ПГ(v) означає, что або вершина v – крапка зчленування, або v=v0 і v не є точкою
зчленування. Помітимо, что другий випадок не вимагає особливого розгляду. У цьому
випадку вилучені зі стека S ребра відповідають єдиному блоку графа, що містить v0. І,
нарешті, остання деталь. Виділення блоку графа G ми розуміємо як видалення всіх ребер
цього блоку зі стека S. Можна вважати, что одночасно з видаленням з S кожне таке ребро
заноситься в деякий інший список, причому безліч ребер різних блоків розділені в цьому
списку, наприклад, символом 0. Процедура побудови цього нового списку очевидна, і щоб не
захаращувати опису алгоритму, ми не приводимо її в явному виді.
Порівняння l(s) із ПГ(v) виробляється |G| - 1 разів, і, отже, сумарний час, витрачений на
виконання порівнянь, складає O(|G|). Кожне ребро графа один раз включається в стек S і
один раз виключається з нього. Тому вся робота, зв'язана зі зміною S, виконується за час O(|
EG|). Таким чином, пошук у глибину разом з виділенням блоків буде виконуватися за час O(|
EG|+|G|).
Алгоритм A2 пошуки в глибину з виділенням двозв’язних компонент.
1. ПГ(v0):=1, l(v0):=1, S:= , F(v0):=0, T:= , B:= , k:=1, p:=1, Q(1):=v0.
2. v:=Q(p).
3. Переглядаючи список NV знайти таку вершину w, что ребро vw не позначене, і перейти до
п.4. Якщо таких вершин ні, то перейти до п.5.
4. Якщо вершина w имееет ПГ- номер, то помістити ребро vw как «зворотне», занести ребро
в стек S, l(v):=min{l(v),ПГ(w)} [ виконане коректування l(v)]. Перейти до п.3 і продовжити
перегляд списку NV. Інакше ребро vw позначити як «пряме», k:=k+1, ПГ(w):=k, l(w):=k,
F(w):=v, p:=p+1, Q(p):=w. Перейти до п.2.
5. p:=p-1. Якщо p=0, то кінець. Інакше перейти до п.6.
6. Нехай x=F(v). Якщо l(v)>=ПГ(x), то перейти до п.7. Інакше l(x):=min{l(x),l(v)} [виконане
коректування l(x)] і перейти до п.2.
7. Видалити зі стека S усі ребра аж до xv [вилучені ребра складають блок графа G] Перейти
до п.2

Приклад. На мал. 74.2 зображений граф G і приведені списки суміжності його вершин. Цей
граф має чотири блоки В1, У2, У3, У4 і дві крапки зчленування d і x. Пошук у глибину
починається з вершини a, тобто v0=a. На мал. 74.3 відбита ситуація, що склалася
безпосередньо перед виділенням блоку B4. До цього моменту шість ребер позначені як
«прямые» і одне как «зворотне». Прямі ребра проведені жирними лініями, а зворотне –
пунктирної. Тим і іншим додана відповідна орієнтація. Позначені ребра розташовані в стеці
S у тім порядку, у якому вони одержували позначки. Пари чисел (,), приписана вершині v,
має наступний сенс: =ПГ(v), а  - значення l(v), обчислене до розглянутого моменту.
Після того, як ребро tx одержало позначку «зворотне», відбулося повернення у
вершину z. При цьому порівняння величин ПГ(z)=6 і l(t)=5 показало, что вершина z не є
точкою зчленування. Далі при поверненні з вершини z у x виявляється, что l(z) = 5 = ПГ(x).
Отже, усі ребра від tx до xz у стеці S складають блок графа G. Ці ребра –tx, tz, xz –
віддаляються з S, і тим самим виділений блок B4.

Після цей алгоритм працює так, ніби блоку B4 у графі G не було взагалі. Ключові
моменти подальшої роботи алгоритму ілюструються на мал. 74.4. Кожний із трьох графів
(разом з їхніми позначками і стеком S), зображених на цьому малюнку, відбиває ситуацію,
що створилася безпосередньо перед видаленням чергового блоку.

Виділення останнього блоку, т.е видалення его ребер зі стека S, відбудеться при
поверненні у вершину v0=a, для якої ПГ(a)=1=l(c). Таким чином, на вершину v0=a алгоритм
«реагує» точно так само, як на крапку зчленування.

На закінчення відзначимо, що пошук у глибину виявляється корисним і при


відшуканні 3-зв'язних компонентів графа. Відомий заснований на пошуку в глибину
алгоритм, що вирішує цю задачу за час O(|EG+|G|).
Лекція 3.1. Мінімальний кістяк
Задача про мінімальний кістяк складається у відшуканні кістяка мінімальної ваги у
зваженому графі (G,w). Вона вважається однією із самих «легких» оптимізаційних задач на
графах. Розв’язок цієї задачі можна одержати за допомогою «жадібного» алгоритму, якщо
вказати процедуру, що за будь-якою ациклічною множиною ребер X EG і ребром e  EG
визначає, чи містить множина ребер Xe цикл графа G. Як таку процедуру можна
використовувати, наприклад, пошук у глибину, оскільки виявлення циклу в безлічі Xe, де
e=ab, рівнозначно відшуканню (a,b) – ланцюга в породженому підграфі G(X). У процесі
роботи «жадібного» алгоритму ця процедура виконується не більше |E| раз, і, отже, витрати
часу складуть O(|EG|*|G|). Для упорядкування безлічі EG за незменшуванностю ваги відомі
алгоритми складності O(|EG|*log|EG|). Таким чином, навіть нехітра реалізація “жадібної”
стратегії пошуку мінімального кістяка приводить (незалежно від способу завдання графа G) ,
до поліноміального алгоритму. З цього погляду задача про мінімальний кістяк дійсно є
легкою.
Ми зараз розглянемо два алгоритми розв’язку цієї задачі, що мають кращі оцінки
швидкодії.
1. Розробка й оцінка алгоритму визначення мінімального кістяка.
Нехай T = {(V1,T1), (V2,T2), ..., (Vk,Tk) } – кістяковий ліс зваженого графа G, Vi, Ti
-безлічі вершин ребер i – й компоненти лісу T, w(x,y) – вага ребра xy графа G. Обидва
алгоритми побудови мінімального кістяка спираються на наступну просту теорему.
Теорема 75.1. Нехай ребро ab має мінімальну вагу серед усіх ребер, y якому рівно
один кінець міститься в VT1. Тоді серед кістяків графа G, що містять T  ab, знайдеться
такий, вага якого не більш ваги будь-якого кістяка, що містить T.
Доказ. Нехай T ’ – довільний кістяк графа G, що містить Т і не утримуючий ребра ab.
Додамо це ребро до Т ’. Отриманий граф буде містити цикл S (теорема 13.1). Цей цикл
включає ребро ab і принаймні ще одне ребро a’b’, у якого рівно один кінець міститься в V1 .
За умовою w(a,b) <= w(а',b’). Отже,
w(T’ + ab -а'b’) = w(T’)+w(ab)-w(a’b’)<=w(T’).
C іншої сторони, граф Т’ + ab – a’b’ є кістяком графа G, що містить Т  ab. 
Зауваження. Легко показати, що кожен мінімальний кістяк повинний містити
принаймні одне з ребер мінімальної ваги графа G. Отже, будь-який алгоритм побудови
мінімального кістяка повинен хоча б раз переглянути усю вхідну інформацію, чи то матрицю
ваги, список ребер чи списки суміжності графа. У противному випадку непереглянуте ребро
може виявитися єдиним ребром мінімальної ваги графа, і це ребро не зможе ввійти в
мінімальний кістяк.
Теорема відразу підказує наступну стратегію побудови мінімального кістяка. На
першому кроці розглянемо кістяковий ліс T 1 з n=|G| компонентами. Кожен його компонент
складається з однієї вершини, тобто Vi1 = {vi} . Цей ліс, очевидно, міститься в будь-якому
кістяку графа G. Серед ребер, інцидентних v1 , виберемо ребро мінімальної ваги v1vk1 і
приєднаємо його до Т1 . Відповідно до теореми 75.1 існує мінімальний кістяк, що містить ліс
Т2 = Т1 {v1vk1}, у якого компонента (V12,T12) містить дві вершини v1 і vk1 і ребро v1vk1 , а інші
компоненти одновершинні. На наступному кроці буде обране і додано до Т 2 ребро
мінімальної ваги серед ребер, що з'єднують {v1vk1} з VG \ {v1vk1} і т.д.
Отже, стратегія побудови мінімального кістяка зовсім ясна: на кожнім кроці
приєднується ребро, мінімальне по вазі серед ребер, що з'єднують уже побудований
фрагмент мінімального кістяка з вершинами, ще не включеними у фрагмент. Нам
залишається тільки подбати про ощадливу реалізацію кроків цього процесу. З цією метою
зв'яжемо з кожною вершиною xVG дві мітки (x) і (x), зміст яких полягає в наступному.
Нехай пророблено k кроків і (V1k,T1k ) – фрагмент мінімального кістяка, побудований до цього
моменту, тобто ця компонента лісу, до якої на попередніх кроках приєднувалися ребра
мимнимальної ваги. Тоді
(x) = min w(x,v) =w(x,v*), (x) = v*
v  V1k
Таким чином, (x) – вага мінімального по вазі ребра, що з'єднує вершину x з побудованим
фрагментом мінімального кістяка, а (x) – ім'я другої вершини цього ребра. Метки (x) і (x)
дозволяють швидко знаходити на кожнім кроці ребро мінімальної ваги. Крім того, після
приєднання чергової вершини v до фрагмента мітки легко відрегувати. Для этого досить
порівняти «старе» значення (x) з w(v,x) і вибрати з них менше в якості «нового» значення
(x).
В описі алгоритму, що приводиться нижче, побудови мінімального кістяка крім ((x) і ((x)
використані наступні позначення: VT, ET - безлічі вершин і ребер споруджуваного
фрагмента мінмального кістяка; Nx - оточення вершини x; |G| = n. Граф G заданий
матрицею ваг.
Алгоритм A3 побудови мінімального кістяка.
1. Покласти ET:=, VT:={a}, де a – будь-яка вершина з VG. Кожній вершині xa,
приписати мітки (x) = w(x,a), якщо xNa і (x) = , якщо xNa , (x) = a.
2. [відшукання вершини, «найближчої» до фрагмента]. Вибрати вершину v*  VG\VT
(v*) = min (v).
v*  VG\VT
3. [збільшення фрагмента]. Нехай v’ = (v*). Змінити VT і ET, вважаючи VT:=VT  {v*},
ET:=ET  v’v*.
4. Якщо |VT| = n, то кінець. Ребра, що знаходяться в множині ET, складають мінімальний
кістяк.
5. Для кожної вершини v Nv*  (VG\VT) змінити мітки в такий спосіб. Якщо (v)>w(v*,v),
то (v):=w(v*,v), (v):=v*. Якщо ж (v)<=w(v*,v), то мітку вершини v не змінювати.
Перейти до п.2.
Теорема 75.2. Алгоритм A3 будує мінімальний кістяк за час O(|G|2).
Доведення. Тому що всякий раз до ET додається ребро, один кінець якого належить
VT, а інший ні, граф T=(VT,ET) на кожнім кроці є деревом. Після завершення роботи
алгоритму це дерево буде кістяковим, оскільки алгоритм припиняє роботу тільки якщо
VT=VG.
Доведемо мінімальність кістяка Т. Для этого досить довести, що після k – го (k=1..n-
1) виконання п.3. алгоритму граф Тk = (VТk, EТk) міститься в деякому мінімальному кістяку.
Доводити будемо індукцією по k. При k=1 наше твердження безпосереднє випливає з
теореми 75.1. Припустимо, что воно справедливо для де-якого k>1, т.ч. граф Т k , побудований
у результаті k виконань п.3, міститься в деякому мінімальному кістяку. З огляду на правило
вибору ребра е для приєднання до Тk , застосуємо теорему 75.1. Одержимо, що граф Т k+1 = Тk
 е, побудований у результаті (k+1) – го виконання п.3, також міститься в деякому
мінімальному кістяку.
З'ясуємо тепер швидкодію алгоритму. Однократне виконання п.2 вимагає не більше
O(|G|). Стільки ж часу досить для відновлення міток у п.5, а п.3 і п.4 виконуються за час O(1).
Оскільки кожний із пп. 2-5 виконується n-1 раз, то оцінка трудомісткості алгоритму O(|G|2).
Приклад 1. На мал. 75.1 зображені граф G і послідовність T i (i=1..n-1) фрагментів
мінімального кістяка, що виходять після кожної ітерації алгоритму. Числа, приписані ребрам
графа G, означають ваги цих ребер. Кожній вершині x , що ще не ввійшла в T i , приписана
пара чисел [(x),(x)], якими вона позначена в результаті i – го виконання п.5 алгоритму.
Якщо граф G заданий матрицею ваг, то всякий алгоритм побудови мінімального
кістяка в такому графі буде мати складність не менш чим O(|G|2) , оскільки він, відповідно до
зауваження 1, повинний переглядати всі елементи матриці ваг. Отже, у цій ситуації алгоритм
A3 має незменшувану один по одному трудомісткість. Якщо ж граф G заданий списком
ребер або списками суміжності і |EG| істотно менше чем |G| 2, то швидкодія алгоритму A3
далеко від оптимального. Іншими словами, алгоритм A3 недостатньо ефективний у
застосуванні до «рідкіх» графів, тобто до графів, слабко насиченними ребрами.
2 Алгоритм побудови мінімального кістяка, орієнтований на роботу з «рідкими»
графами. Цей алгоритм (алгоритм A4 ), як і попередній, спирається на теорему 75.1, однак
більш повно використовує надані нею можливості. Саме, якщо в алгоритмі A3 ребро
приєднується всякий раз до одній і тієї ж компоненту лісу, то в алгоритмі A4 ребра
приєднуються до кожного компонента.
Нехай T = {(V1,T1), (V2,T2), ..., (Vp,Tp) } – кістяковий ліс графа G. Назвемо ребро ab
мінімальним по вазі для компонента (Vl,Tl), 1<=l<=p, якщо a Vl, b Vl, і w(a,b) = min
w(x,y), x Vl, y Vl . Будемо говорити, що M=M(T) множин--безліч мінімальних по вазі ребер
для лісу Т, якщо для каждого l=1..p безліч М містить хоча б одне мінімальне по вазі ребро
для коипоненти (Vl,Tl) і, крім того, М – мінімальне по включенню безліч, що володіє цією
властивістю.
Теорема 75.3. Якщо М = безліч мінімальних по вазі ребер для T = {(V1,T1),
(V2,T2), ..., (Vp,Tp) } то граф T’=T+M не містить циклів.
Доказ. Доводимо від противного. Припустимо, что T містить цикл S, що не втрачаючи
спільності будемо вважати простим. Нехай a1b1, a2,b2, ...,al,bl – ребра безлічі S  M,
виписані в тій послідовності, як вони розташовані в циклі S. Цієї послідовності відповідає
послідовність компонентів (Vk1, Tk1), (Vk2, Tk2), ... , (Vkl, Tkl) лісу Т, така, що a1 Vk1 , b1 Vk2 ,
a2 Vk2, b2 Vk3 , ... , al Vkl , bl Vkl виберемо серед ребер aibi (i=1..l) максимальне по вазі.
Нехай це буде ребро a1b1. Ясно, що a1b1 є мінімальним по вазі ребром принаймні для одного з
компонентів (Vk1, Tk1), чи (Vk2, Tk2). Не втрачаючи спільності вважаємо, що ребро a1b1
мінімальне по вазі для (Vkl, Tkl). Тоді w(a1 ,b1) = w(al ,bl) і, отже, безліч М\ a1 ,b1 містить хоча б
одне мінімальне по вазі ребро для кожного компонента лісу Т. Останнє суперечить
мінімальності безлічі М. 
Перейдемо тепер до викладу алгоритму A4. Цей алгоритм, також, як і A3 , на першій
ітерації має справу з кістяковим лісом графа G, що складає з n=|G| одновершинних
компонентів. Кожна ітерація алгоритму складається в наступному. Спочатку будується
безліч М мінімальних по вазі ребер для лісу Т, отриманого в результаті попередніх ітерацій.
(Важливо відзначити, что зробити це можна за один перегляд елементів безлічі EG.) Потім за
допомогою пошуку в глибину виділяються зв'язні компоненти графу T’=T+M, що відповідно
до твердження 75.2 є лісом. Після цього починається наступна ітерація з новим лісом T’, що
має очевидно, менше компонент, ніж T.
В описі алгоритму А4, що приводиться нижче, використовуються наступні
позначення. Ребра графа G містяться в списку E, т.ч. E(і) - пари номерів кінцевих вершин i-
го ребра. Список W містить ваги ребер графу G, тобто W(і) – вага i-го ребра. Щоб щораз
будувати безліч мінімальних по вазі ребер для поточного лісу за один перегляд списку E,
використовуються списки HMP, BMP і КОМП:
HMP(i) - номер мінімального по вазі ребра для i-й компоненты поточного лісу;
BMP(i) - вага цього ребра;
КОМП(i) – номер компонента поточного лісу, що містить вершину j.
Нехай, далі, ET – безліч ребер поточного лісу T, a p – число его компонентів; E1 –
безліч мінімальних по вазі ребер для поточного лісу Т.

Алгоритм A4 побудови мінімального кістяка.


1. ЕТ:=(, КОМП(і):=і, BMP(і):=( для і=1..n, p:=n. [Пп. 2-8 – побудова безлічі Е1 мінімальних
по вазі ребер для лісу T] .
2. k:=1.
3. Нехай Е(k) = uv; і:=КОМП(u), j:=КОМП(v) [і і j – номера компонентів лісу, що містять
вершини u і v відповідно].
4. Якщо і(j, то перейти до п.5, інакше перейти до п.7.
5. Якщо w(u,v)=W(k)<BMP(j), то BMP(j):=w(u,v), HMP(j):=k.
6. Якщо w(u,v) = W(k)<BMP(і), то BMP(і):=w(u,v), HMP(і):=k.
7. Якщо k=|EG|, то перейти до п.8. Інакше k:=k+1 і перейти до п.3. [ДО моменту виконання
п.8. перші p елементів HMP містять номера ребер, що складають безліч мінімальних по
вазі ребер для T.]
8. Переглянути перші p елементів масиву HMP і сформувати безліч Е1 мінімальних по вазі
ребер для лісу Т.
9. ЕТ:=ET ( E1 [ЕТ – безліч ребер «нового» лісу Т'].
10. Виділити за допомогою алгоритму пошуку в глибину зв'язні компоненты графы Т’=T+E1
[обновлений список КОМП, отримане нове значення р].
11. Якщо р=1, то кінець [ЕТ - безліч ребер мінімального кістяка]. Інакше перейти до п.2.
Теорема 75.4. Алгоритм A4 будує мінімальний кістяк за час O(|EG|log|G|).
Доказ. Неважко переконатися, что після кожного виконання п.8 безліч Е1 є безліччю
мінімальних по вазі ребер для лісу Т, розглянутого в цей момент. Тому відповідно до
твердження 75.2 граф Т’ = T+E1 знову є кістяковим лісом. Це означає, что алгоритм будує
деякий кістяк графа G. Мінімальність цього кістяка доводиться за допомогою теореми 75.1
точно так само, як при обґрунтуванні попереднього алгоритму. З'ясуємо тепер швидкодію
алгоритму A4. Для однократного виконання кожного з пп. 3-6 досить часу ПРО(1) і, отже,
побудова Е1 здійснюється за час ПРО(|EG|). Таких самих витрат досить і для однократного
виконання пп. 8-11. Таким чином, витрати на перехід від Т к Т' = T +E1 (тобто на виконання
однієї ітерації) складають ПРО(|EG|) операцій. Оцінимо тепер число ітерацій алгоритму.
Оскільки одне ребро може бути мінімальним по вазі не більш ніж для двох компонентів лісу
Т, то на кожній ітерації |E1| >= p(T)/2. А тому що T+E1 – ліс, то p(T+E1)<=p(T)/2, тобто на
кожній ітерації число компонент зменшується принаймні вдвічі. Це означає, что число
ітерацій алгоритму не перевершує log|G|, отже, він будує мінімальний кістяк за час O(|EG|log|
G|).

Мал. 75.2
Приклад 2. Застосуємо алгоритм A4 до графу, зображеному на мал. 75.2 На першій
ітерації буде знайдена безліч E1={a1a2, a1a3,a4a7,a5a8,a6a9,a9a10} мінімальних по вазі ребер
для лісу, що має одновершинні компоненты. Кістякові ліси, отримані в результаті виконання
1-й, 2-ї, і 3-ї ітерацій, зображені на мал. 75.3. Останній з них є мінімальним кістяком.

Лекція 3.1. Розробка й оцінка алгоритмів пошуку найкоротших шляхів у графах


Нехай G=(V,A) – орієнтований зважений граф. Задача про найкоротший шлях
складається у відшуканні шляху мінімальної ваги, що з'єднує задані початкову і кінцеву
вершини графа G за умови, що хоча б один такий шлях існує. Початкову і кінцеву вершини
позначимо відповідно через s і t; (s,t) – шлях мінімальної ваги будемо називати
найкоротшим (s,t) – шляхом.
1. Алгоритм пошуку найкоротших шляхів у графах з невід’ємними вагами всіх дуг.
Отже, розглядаємо графи, у яких w(e)>=0 для кожної дуги e(A. У цьому випадку розв’язок
задачі про найкоротший шлях є істотно менш трудомістким, чим у загальному. Перший
ефективний алгоритм побудови найкоротшого шляху в графі з невід’ємними вагами дуг
запропонував Е. Дейкстра в 1959 р.
На кожній ітерації цього алгоритму будь-яка вершина v графа G має мітку l(v), що
може бути постійною або тимчасовою. У першому випадку l(v) – вага найкоротшого (s,v) –
шляху. Якщо ж мітка l(v) тимчасова, то l(v) – вага найкоротшого (s,v) – шляху, що проходить
тільки через вершини з постійними мітками. Таким чином, тимчасова мітка l(v) є оцінкою
зверху для ваги найкоротшого (s,v) – шляху, і ставши на деякій ітерації постійної, вона
залишається такий до кінця роботи алгоритму. Крім l(v), з кожною вершиною v графа G, за
винятком s, зв'язується ще одна мітка - ((v). На кожній ітерації ((v) є номер вершини, що
передує v у (s,v) – шляхів, що проходять через вершини, що одержали до даного моменту
постійні мітки. Після того як вершина t одержала постійну мітку, за допомогою міток ((v)
легко вказати послідовність вершин, що складають найкоротший (s,t) – шлях.
Перед початком першої ітерації алгоритму вершина s має постійну мітку l(s) =0, а
мітки l всіх інших вершин рівні  і ці мітки тимчасові.
Загальна ітерація алгоритму складається в наступному. Нехай p – вершина, що
одержала постійну мітку l(p) на попередній ітерації. Переглядаємо усі вершини v(Г(р), що
мають тимчасові мітки, з метою зменшення (якщо це можливо) цих міток. Мітка l(v)
вершини v(Г(р) замінюється на l(p)+w(p,v), якщо виявилося, що вершина v одержала свою
мітку l з вершини p, і думаємо ((v)=p. Якщо ж l(v)<=l(p)+w(p,v), то мітки ( і l вершини v не
змінюються на даній ітерації. Алгоритм закінчує роботу, коли мітка l(t) стає постійною. Як
вже говорилося вище, l(t) -найкоротшого (s,t) -шляху, що будемо позначати через P*. Цей
шлях визначається за допомогою міток  так:
P*=(s, ..., 3(t), 2(t), (t),t),
Де  =((...((v) ...)) для будь-якої вершини v ( VG.
k

K раз
Будемо вважати, что граф G заданий матрицею ваг або списками суміжності.
Алгоритм A4 Дийкстры пошуки найкоротшого шляху.
Мал. 75.2
1. Покласти l(s):=0 і вважати цю мітку постійною. Покласти l(v) := ( для всіх v ( VG,
v(s, і вважати ці мітки тимчасовими. Покласти p:=s.
2. Для всіх v ( Г(p) з тимчасовими мітками виконати: якщо l(v)>l(p)+w(p,v), те
l(p):=l(p)+w(p,v) і ((v):=p. Інакше l(v) і ((м) не змінювати.
3. Нехай V' – безліч вершин з тимчасовими мітками l. Знайти вершину v*, таку що
l(v*) = min l(v).
v(V(
Вважати мітку l(v*) постійною міткою вершини l(v*).
4. p := v*. Якщо p = t, то перейти до п. 5 [l(t) – вага найкоротшого шляху]. Інакше
прейти до п. 2.
5.
P * : ( s,..., 3 (t ), 2 (t ), (t ), t )
[P* – найкоротший шлях]. Кінець.
Перш ніж перейти до обґрунтування алгоритму, зробимо три корисних зауваження.
Зауваження 1. Як легко бачити, алгоритм А5 застосовуємо до змішаного і , в
частково, до неорієнтованих графам. Для цього досить кажне неориєнтоване ребро uv графу,
що має вагу w(u, v), розглядати як пари дуг (u, v) і (v, u) тієї ж ваги.
Зауваження 2. Якщо п. 4 модифікувати таким чином, щоб алгоритм закінчував роботу
тілько після одержання усіма вершинами постійних міток, то він буде будувати найкоротші
шляхи з s у кожну з інших вершин. Якщо до того ж разом з перетворенням метки вершини v*
у постійну (п. 3 алгоритму) заносити дугу ((v*), v*) у безлічі А*, то після закінчення роботи
алгоритму граф D = (VG, A*) буде кореневим орієнтованим кістяковим деревом. Це дерево
називається деревом найкоротших шляхів з s графа G. Для будь-якої вершини vVG єдиний
шлях (s, v)-шлях у дереві D є найкоротчшим (s, v)-шляхом у графі G.
Зауваження 3. Алгоритм А5, модифікований так, як зазначено в зауваженні 2, можна
розглядати як алгоритм побудови дерева D найкоротших шляхів з вершин s графа G. З цього
погляду алгоритм А5 анологічен алгоритму А3 побудови мінімального кістяка. дійсно,
побудова дерева D складається в послідовному збільшенні вже побудованого фрагменту
шляхом додавання деякої дуги, “вихідної” з цього фрагмента. При цьому влучні l і  грають
таку ж роль, як і мітки  і  в алгоритмі А3.
Теорема 76.1. Алгоритм А5, будує в графе G найкоротший (s, t)-шлях за час
Доказ. Помітимо спочатку, що мітка вершини v (l(v) (() дорівнює вазі (s, v)-шляху, що
O(| G |2 ).
побудований алгоритмом до цього моменту. Він визначається мітками (, що маються на цей
момент. Тому для доказу оптимальності (s, t)-шляху, що відповідає постійній мітці l(t),
досить довести, що постійна мітка l(v) кожної вершини v дорівнює ваги найкоротшого (s, v)-
шляху. Це твердження будемо доводити по індукції. Нехай вершина v отримала свою
постійну мітку на k-й ітерації, тобто після k-го виконання п. 3. При k = 1 справедливість
твердження очевидна. Припустимо, що воно вірно для вершин, що одержали свої постійні
мітки на ітераціях 2, 3, ..., k – 1. Позначимо через P( (s, t)-шлях, побудований алгоритмом у
результаті k ітерацій, а через Р* – найкоротший (s, v)-шлях. За умовою w(P() = l(v).
Нехай V1 і V2 – безлічі вершин, що мають відповідно постійні і тимчасові мітки
перед початком k-ї ітерації. Розглянемо дві можливі ситуації:
а) Шлях Р* містить вершини з V2. Нехай (v – перша (вважаючи від s) така вершина,
що належить Р*, а вершина v( передує(v на шляху Р*, тобто (v(,(v)(AP*. Відповідно до
вибору(v маємо v((V1. Позначимо через Р1* частину шляху Р* від s до(v. По припущенню
індукції l((v) – вага найкоротшого (s, (v)-шляху. Тому
w(Р1* ) = l((v) + w(v((v) ( l((v).
Оскільки l((v) – тимчасова мітка, а остання мітка l(v) вершини v вибирається на k-й ітерації
як найменша з тимчасових, то l((v) ( l(v). Об'єднавши цю нерівність з (1), одержимо
w(P*) ( w(P1*) ( l(v) = w(P(),
т. ч. P( – найкоротший (s, t)-шлях.
б) Усі вершини шляху Р* входять у V1. Нехай v( і v(( – такі вершини, що (v(, v)(АР* і
(v((, v)(АР(. Позначимо через Р( частина шляху Р* від s до v(, відповідно до припущення
індукції маємо w(P() ( l(v(). Тому, якщо v( = v((, то відразу одержуємо нерівність
w(P*) = w(P() + w(v(, v) ( l(v() + w(v(, v) = w(P().
Допустимо тепер, що v(( ( v(. Оскільки v одержує постійну мітку l(v) з v((, а не з v(, те
V(P*) = l(v() + w(v(, v) ( l(v(() + w(v((, v) = w(P().
Таким чином, і у випадку б) вірна нерівність w(P() ( w(P*), тобто P( – найкоротший (s,
v)-пута.
Оцінимо тепер трудомісткість алгоритму. Обчислювальні витрати максимальні, коли
вершина t одержує постійну мітку останньої і граф G є повним. У цьому випадку число
ітерацій алгоритму дорівнює |G| – 1, тобто кожний із пп. 2 – 4 виконується |G| – 1 разів.
Очевидно, що п. 4 виконується за час ПРО(1), а для виконання кожної з пп. 2, 3 досить часу
ПРО(|G|).
Мал. 76.1

Побудова шляху за допомогою міток  можна здійснити, витративши не більше ПРО(|G|)


операцій. Таким чином, в цілому час побудови найкоротшого (s, t)-шляху не перевершують
O(| G |2 ).

( k  1, 5)
Приклад 1. На мал. 76.1 зображені п'ять копій Gk , k = 1,…,5 графа G, кожна з яких
відбиває ситуацію, що склалася після чергової ітерації алгоритму. Біля кожної дуги написана
її вага. Вершинам копії Gk приписані влучні, отримані ними в результаті виконання перших
k ітерацій. Деякі дуги обведені жирними лініями, тобто відзначені. Додання такої дуги (a, b)
при переході від Gk до Gk+1 означає, що вершина b одержала свою мітку l(b) з a і ця мітка
стала постійною на (k + 1)-й ітерації. Вершина t у нашому прикладі одержує постійну мітку
останньої, і відзначені дуги G5 утворять дерево найкоротших шляхів з s.
При розв’язанні багатьох задач виникає необхідність відшукання в незваженому графі
(s, t)-шляху з мінімальною кількістю дуг. Такий шлях, мабуть, можна знайти за допомогою
алгоритму Дейкстри. Для цього досить привласнити всім дугам графу G ваги, рівні 1, і
застосувати алгоритм А6. Останнім роботу алгоритму в цій ситуації, звертаючи особливу
увагу на послідовність, у якій вершини графа G одержують постійні мітки. Очевидно, що
спочатку постійні мітки l = 1 одержать усі вершини безлічі Г(s). Потім мітка l = 2 буде
привласнена кінцям дуг, що виходять з вершин з мітками l = k –1. Цей процес обходу (і
присвоєння міток) вершин графа називають пошуком у ширину в графі (на інтуїтивному рівні
пошук у ширину описаний у параграфі 9). По закінченні пошуку в ширину мітка l(x)
вершини x дорівнює мінімальному числу дуг у (s, x)-шляху. Как і раніше, сам цей шлях
визначається мітками . Здійснення пошуку в ширину за допомогою алгоритму Дейкстри
зв'язано, як ми знаємо, з обчислювальними витратами
O(| G |2 ).
2. Алгоритм пошуку в ширину. Розглянемо алгоритм А6, що здійснює пошук у
ширину за час O(|EG|). У цьому алгоритмі мітки l і ( грають ту ж роль, що й у попередньому,
з тієї, однак, різницею, що мітки l не поділяються на тимчасові і постійні. Як тільки вершина
x одержує мітку l(x) ( (, ця мітка відразу стає постійною (тобто остаточною). За рахунок
цього, зокрема, досягається економія часу обчислень у порівнянні з алгоритмом Дейкстри.
Особливу роль в алгоритмі А6 грає список Q. Кожна вершина графа один раз
заноситься в цей список і один раз з нього викреслюється. При цьому викреслюється увесь
час перша (на поточний момент) вершина цього списку, а тільки що додана вершина завжди
є останньої в списку, тобто Q-черга. На початку в Q знаходиться єдина вершина s, l(s=0), а
всі інші вершини міток не мають. Загальна ітерація складається в наступному. Вибирається
перша вершина х у списку Q. Кожній не поміченій вершині y  Г(x) привласнюються мітки
l(y)=l(x)+1 і (y)=x, після чого вершина в стає останньої в списку Q, а вершина х
віддаляється з Q. Алгоритм припиняє роботу, як тільки в Q не залишиться жодної вершини.
При цьому вершини, досяжні з s, будуть мати мітки, а недосяжні – не матимуть. Для
швидкого виконання операцій викреслювання і включення в Q використовуються змінні
покажчики p і q – адреси першої й останній зайнятих осередків списку Q відповідно.
Будемо вважати, что граф G заданий списками суміжності і Nv – список, що містить
конци всіх дуг, що виходять з вершини v.
Алгоритм А6 пошуку в ширину.
1. Q(1):=s, p:=1, q:=1, l(s):=0.
2. x:=Q(p), m:=|Г(x)| [обрана перша вершина x черги Q].
[П.п. 3 – 5 присвоєння міток не позначеним вершинам з Г(x)].
3. k:=1.
4. Якщо вершина в = Nx(k) має мітку, то перейти до п. 5. Інакше l(y):=l(x)+1,
(y):=x, q:=q+1, Q(q):=y [вершина в позначена і включена в чергу Q] і перейти до
п.5.
5. Якщо k=m, то перейти до п.6, інакше k:=k+1 і перейти до п.4.
6. p:=p+1 [вершина x виключена з Q].
7. Якщо p>q, то кінець [Q = 0, тобто усі вершини досяжні з s, одержали мітки],
інакше перейти до п.2.
Теорема 76.2. Алгоритм А6 привласнює мітки l і  усім вершинам графа, досяжним з
вершини s за час ПРО(|EG|). При цьому
 s, , 3 ( x), 2 ( x), ( x), x   (s, x)  путь
з мінімальним числом дуг, а l(x) – число дуг у цьому шляху.
Основні обчислювальні витрати пов'язані з виконанням п. 3 алгоритму. Сумарний час
виконання цього пункту складає
O (  | N v | )  O ( | EG | )
vVG

оскільки кожний зі списків Nv проглядається в точності один раз. Витрати на виконання


інших пунктів, мабуть, не перевершують цієї величини.
Вище відзначалося, что результати алгоритму А6 (тобто мітки l і ) ті ж, що й в
алгоритмі Дейкстри, якщо кожній дузі графа G приписати вага, рівна 1. Тому справедливість
другого твердження випливає з твердження 76.1.
Зауваження 4. Іноді потрібно шукати шляхи з вершин безлічі X ( VG
в усі інші вершини. Для розв’язку цієї задачі достаточно злегка модифікувати алгоритм А6,
зміни в ньому п. 1. Саме, у списог Q варто помістити усі вершини x Є X. На модифікований
у такий спосіб алгоритм А6 будемо посилатися як на пошук у ширину з безлічі X.
3. Алгоритм пошуку найкоротших шляхів у графах з від’ємними вагами дуг.
Перейдемо тепер до розгляду загальної ситуації. Будемо вважати, що в графі G
пдопускаються дуги від’ємної ваги. Запропонований нижче алгоритм А7 будує в такому
графі найкоротші шляхи між усіма парами вершин графа за умови, що в графі немає
від’ємних контурів (контурів від’ємної ваги). Якщо ж такий контур у графі є, то алгоритм
сповіщає про це і припиняє роботу, залишаючи задачу відшукання найкоротшого шляху
невирішеною (див. нижче зауваження 6).
Будемо вважати, что граф G, |G| = n, заданий матрицею ваг W = ||Wij||, тобто Wij = (i,
j), якщо (i, j) Є AG, і Wij = 
противному випадку. Крім того, припускаємо Wij = 0 для всіх і = 1, 2, ..., n. Алгоритм
заснований на наступних розуміннях. Нехай i, j, k – три будь-які вершини графа G, і ми
хочемо одержати (i, j)-шлях, найкоротший серед (i, j)-шляхів, що не містять внутрішні
вершини, відмінних від k. Очевидно, что для этого досить вибрати меншу з двох величин
Wij і Wik + Wkj, що і буде вагою такого (i, j)-шляху. Якщо зафіксувати k і проробити цю
операцію (назвемо її t-операцією, застосованої до індексу k) для всіх пар (i, j), то одержимо
матрицю W’ = ||W’ij||, у якої W’ij = min{Wij, Wik + Wkj}. Виявляється (це буде пізніше
доведене), маючи матрицю
ваг найкоротших шляхів, що проходять тільки через вершини безлічі S  VG
можна одержати таку ж матрицю для шляхів, що проходять через безліч
Ws
S  {m}, m  S .
Для цього досить точно застосувати t-операцію до індексу m і всім елементам матриці

W s.
Саме в цьому складається ітерація алгоритму А7, що, починаючи з W = W,
W 0 ,W 1 , ,W n , что W m получается
изW m1

W m 1 .
будує таку послідовність матриць застосуванням t-операції до індексу m і матриці
Якщо в графі G немає від’ємних контурів, то елемент
Wijm матрици W m
при кожному m дорівнює вазі найкоротшого (i, j)-шляху, усі внутрішні вершини якого
належать безлічі {1, 2, ..., m}. Таким чином, остання з цих матриць,
містить ваги найкоротших шляхів між усіма парами вершин графу. Для того щоб після
W n,
закінчення роботи алгоритму мати можливість швидко знайти найкоротший шлях між будь-
якою парою вершин, будемо на k-й ітерації разом з матрицею

Wk
будувати матрицю
P k || Pijk || .
Спочатку думаємо

Pij0  i (i, j  1, n.
Далі, на k-й ітерації думаємо
Pijk  Pijk 1 , если Wijk  Wijk 1 , иPijk  Pijk 1 , если Wijk  Wikk 1  Wkjk 1 .

Таким чином, Pijk 

номер вершини, що передує вершині j у поточному (i, j)-шляху, тобто в найкоротшому (i, j)-
шляху, усі внутрішні вершини якого містяться в безлічі {1, 2, ..., k}. Матриця
P n  | Pijn |
грає ту ж роль, що й мітки  у попередніх алгоритмах А5 і А6. За допомогою цієї матриці
найкоротший (i, j)-шлях L(i, j) визначається в такий спосіб: L(i, j) = (i, ..., j3, j2, j1, j), де
j1  Pijn , j2  Pijn1 , j3  Pijn2 ,...
Алгоритм А7 відшукання найкоротших шляхів між усіма парами вершин.
1.
W 0 : W , k : 1, P 0 :|| Pij0 ||, гдеPij0  i, еслиWij  , иPij0  0
у противному випадку.
2. Виконати для всіх
i, j  1, n : если Wijk 1  Wikk 1  Wkjk 1 , то Wijk : Wijk 1 , Pijk : Pijk 1 .
Иначе Wijk : Wikk 1  Wkjk 1 , Pijk : Pkjk 1 .
3. Якщо для деякого l,
1  l  n,Wllk  0,
то кінець [у графе маємо від’ємний контур]. Інакше перейти до п. 4.
4. k:=k+1. Якщо k=n+1, то кінець
[W n || Wijn || 
матриця ваг найкоротших шляхів, обумовлених за допомогою матриці
P n || Pijn ||].
Зауваження 5. Алгоритм буде застосовний до змішаних графів, якщо кожне
неорієнтоване ребро замінити на двох дуг тієї ж ваги (див. зауваження 2). При цьому варто
врахувати, что неорієнтоване ребро від’ємної ваги приводить до від’ємного контуру.
Зауваження 6. Алгоритм «відмовляється» будувати найкоротші шляхи, коли в графі
G маються від’ємні контури. У цьому випадку задача відшукання найкоротшого шляху між
двома вершинами (чи між усіма парами вершин) залишається коректною, але стає дуже
важкою. Можна показати, что вона не менш важка, чим, наприклад, задача про комівояжера.
Перейдемо тепер до обґрунтування алгоритму А7 і оцінювання його трудомісткості.
Теорема 76.3. Нехай зважений орієнтований мультиграф L має ейлеровий ланцюг, що
з'єднує вершини a і b. Якщо в L немає від’ємних контурів, то в ньому є такий (a, b)-шлях Р,
що w(L)  w(P).
Доказ. Будемо вважати, що мультиграф L не є шляхом (інакше твердження
тривіальне). Тому він містить деякий контур S. Видаливши з L усі дуги цього контуру,
одержимо мультиграф L’. Оскільки w(S)  0, то w(L)  w(L).
Крім того, відповідно до теореми 65.2 напівступеня вершин мультиграфа L’ задовольняють
співвідношенням
d  (a )  d  (a )  1, d  (b)  d  (b)  1, d  (v)  d  (v), v  a, b.
Тому вершини a і b належать до однієї її слабкої компоненти L’’, і остання містить
ейлеров (a, b)-ланцюг. Продовжуючи подібним чином, одержимо необхідний (a, b)-шлях.
Теорема 76.4. Якщо в графі немає від’ємних контурів, то при всіх
k , i , j  1, n Wijk 
вага найкоротшого (i, j)-шляху, усі внутрішні вершини якого містяться в безлічі {1, 2, ..., k}.
Доказ. Доводимо індукцією по k. При k=1 справедливість твердження очевидна.
Припустимо, что воно справедливо для 2, 3, ..., k – 1, і розглянемо
Wijk . Пусть P 0 
найкоротший (i, j)-шлях, усі внутрішні вершини якого належать безлічі {1, 2, ..., k}. Якщо
P 0 не включает вершину k , то Wijk  Wijk 1
і, відповідно до припущення індукції,
w( P 0 )  Wijk 1  Wijk 1 .
Допустимо тепер, что P містить вершину k. Позначимо через
P10 и P20 части пути P 0
від i до k і від k до j відповідно. Припустимо, что один з цих шляхів, наприклад
P10 ,
не є найкоротшим, і нехай P’ – найкоротший (i, k)-шлях, усі вершини якого містяться в
безлічі {1, 2, ..., k-1}. Розглянемо мультиграф L, що виходить із графа
P /  P20 ,
заміною кожної дуги, що входить одночасно в
P / и P20 ,
двома екземплярами цієї дуги. Очевидно, що L не містить від’ємних контурів. Тому,
відповідно до твердження 76.3, L містить такий (i, j)-шлях Р, що
w( L)  w( P) и, следовательно, w( P 0 )  w( P10 )  w( P20 )  w( P / )  w( P20 )  w( L)  w( P).
Ця нерівність суперечить мінімальності P.
Таким чином, шляху
P10 и P20
Є найкоротшими серед, відповідно, (i, k)- і (k, j)-шляхів, усі внутрішні вершини яких
належать безлічі {1, 2, ..., k – 1}. Тому, скориставшись припущенням індукції, одержимо

Wijk  Wikk 1  Wkjk 1  w( P10 )  w( P20 )  w( P 0 ).


Теорема 76.5. Час роботи алгоритму А7 не перевершує O(|G|3). Якщо граф не містить
від’ємних контурів, то Wnij - вага найкоротшого (i, j)-шляху в графе G для всіх i,j = 1,…,n,n=|
G|... Якщо ж такі контури в графе є, то існують такі числа m і l, что Wmll < 0.
Доказ. Справедливість першого твердження теореми очевидна, оскільки кожна з не
більш чем |G| ітерацій виконується за час O(|G|3)
Друге твердження теореми безпосередньо випливає з теореми 76.4.
Допустимо тепер, что граф G містить від’ємні контури. Нехай m – такий найменший
індекс, що для деякої вершини l у графе G маємо від’ємний контур S, що містить только l і
деякі вершини безлічі {1, 2, ..., m}. Ясно, что контур S включає вершину m. Тоді при будь-
яких i,j = 1,…,n число Wm-1ij дорівнює вазі найкоротшого (i,j)-шляху, усі внутрішні вершини
якого належать безлічі {1, 2, ..., m – 1}. Доказ цього факту дослівно повторює доказ теореми
76.4. Контуру S відповідають (l, m)-шлях Р1 і (m, l)-шлях Р2, такі, що Р1 ( Р2 = S.
Оскільки внутрішні вершини шляхів Р1 і Р2 належати безлічі {1, 2, ..., m – 1}, то
w( P1 )  Wmlm 1 , w( P2 )  Wlmm 1 .
Отже,
Wmlm1  Wlmm1  w( P1 )  w( P2 )  w( S ), т.e. Wllm  min{0, Wlmm1  Wmlm1}  0.

Мал. 76.2

Приклад 2. Нижче приведені результати виконання кожної з чотирьох ітерацій


алгоритму для графу, зображеного на мал. 76.2:
0 2 3  3 0 1 1 1
 0 2   2 0 2 2
W0  W   , P0   ,
  0  3 3 3 0 3
   
4 5 5 0  4 4 4 0

0 2 3  3 0 1 1 1
 0 2   2 0 2 2
W1   , P1   ,
  0  3 3 3 0 3
   
4 2 5 0  4 1 4 0

0 2 0  3 0 1 2 1
 0 2   2 0 2 2
W2  , P2   ,
  0  3 3 3 0 3
   
4 2 4 0  4 11 2 0

0 2 0  3 0 2 1
 0 2  1 2 0 2 3
W3  , P3   ,
  0  3 3 3 0 3
   
4 2 4 0  4 1 2 0
P2144  4, P244  3, P234  2.
P
Знайдемо, наприклад, за допомогою матриці P4 найкоротший (2, )-шлях: P421 = 4, P424 = 3, P423
= 2. Отже, (2, 3, 4 , 1) – найкоротший (2,1)-шлях.

0 2 0  3 0 1 2 1
3 0 2  1 4 0 2 3
W4  , P4   .
1 1 0  3 4 1 0 3
   
4 2 4 0  4 1 2 0

Лекція 3.1. Найбільші паросполучення і задача про призначення

Задача про побудови найбільших паросполучень у графі широко поширена, і для її


розв’язку існують ефективні алгоритми. Ці алгоритми засновані на методі ланцюгів, що
чергуються, основаному на роботах Дж. Петерсону. У даній лекції ми розглянемо декілька
ефективних алгоритмів, побудованих на цьому методі.
1. Алгоритми побудови найбільших паросполучень. Нехай М – паросполучення в
графі G. Ланцюг графа G, ребра якого по черзі входять і не входять у М, називається
ланцюгом що чергується відносно М. Ланцюг довжини 1 по визначенню також чергується.
Ребра ланцюга називаються темними чи світлими, якщо вони чи входять, відповідно, не
входять у М. Вершини графа G, інцендетні ребрам з М, називаються насиченними, всі інші
вершини – ненасиченними. Розглянемо, наприклад, граф на мал. 77.1. Безліч ребер
М = {e1, e7, e10} (1)
є в G паросполученням;
P = {7, 8, 4, 1, 2, 5} (2)
– що чергується відносно М ланцюг; e1 = {1, 2}, e10 = {4, 8} – темні ребра Р; e3 = {1, 4}, e5
= {2, 5}, e13 = {7, 8} – світлі ребра Р; {1, 2, 3, 4 , 6, 8} і {5, 7, 9, 10} – безлічі насичених і
ненасичених вершин відповідно.

мал. 77.1.

Очевидно, что якщо в графе G існує ланцюг що чергується відносно паросполучення


М ланцюг, то можна побудувати в G паросполучення з більшим числом ребер, ніж у М.
Справді, у такому ланцюзі число темних ребер на одиницю менше числа світлих.
Видаливши з М усі темні ребра і приєднавши усі світлі, одержимо нове паросполучення, у
якому число ребер на одиницю більше. З цієї причини ланцюг що чергується відносно
паросочетания М ланцюг, що з'єднує дві різні ненасиченні вершини, будемо називати
збільшуючим відносно М ланцюгом у графі G.
Отже, відсутність увеличивающих відносно М ланцюгів необхідно, щоб
паросполучення М було б найбільшим. Ця умова виявляється і достатньою.
Теорема 77.1. Паросполучення М в графі є найбільшим тоді і только тоді, коли в
цьому графі немає збільшуючих відносно М ланцюгів.
Доказ. Необхідність умови теореми, як вище відзначалося, очевидна. Достатність
доведемо від противного. Нехай М1 також є паросполученням у G і |М1| > |M|. Розглянемо
граф Н, утворений ребрами, що входять у суму М и М1 по модулі 2, тобто в (M  M1)\(M 
M1). Тому що довільна вершина v цього графа инцідентна не більш ніж одному ребру
кожного з паросполучень М и М1 , то її ступінь не більше чим 2. Якщо deg v = 2, то одне з
инцідентних вершині v ребер входить у М, інше в – М1. Тому будь-який зв'язний компонент
графа Н є або циклом, що містить те саме число ребер з М и з М1, або ланцюгом що
чергується відносно М. Але |M1| > |M|, отже, серед цих компонентів обов'язково є ланцюгом
що чергується відносно М , крайні ребра якої (перше й останнє) входять у М1. Тоді крайні
вершини цього ланцюга не насичені паросполученням М, що суперечить умові теореми. 
Для ілюстрації знову звернемося до графа G на мал. 77.1. Що чергується відносно
паросполучення (1) ланцюг (2) з'єднує ненасиченні вершини 5 і 7. Отже, можна побудувати
паросполучення М' з великим числом ребер:
M /  ( M \ {e1 , e10 }) {e3 , e5 , e13 }  {e3 , e5 , e7 , e13 }.
Паросполучення М’ також не є найбільшим: (9, 10) – збільшуючийся відносно М’
ланцюг. Паросполучення
– найбільше, ?(G) = 5.
M //  M / {e15 }  {e3 , e5 , e7 , e13 , e15 }
Таким чином, теорема 77.1 підказує наступну стратегію пошуку найбільшого
паросполучення: почавши з довільного паросполучення М, будувати послідовність М1 = М,
М2, М3 ..., у якій паросполучення Мк+1 виходить із Мк за допомогою тільки що розглянутої
зміни уздовж деякого ланцюга, що збільшується. Оскільки | Мк+1 | = | Мк | + 1, то задля
одержання найбільшого паросполучення буде потрібно не більш |G|/2 ітерацій (тобто
переходів від Мк до Мк+1). У якості М можна взяти, наприклад, довільне ребро чи графа,
що краще, деяке максимальне паросполучення, так що вихідне паросполучення завжди є в
нашому розпорядженні. Тому розробка ефективного алгоритму, заснованого на зазначеній
стратегії, зводиться до побудови процедури, що швидко знаходиться ланцюг, що
збільшується, у графі, або виявляє його відсутність. Обмежимося випадком двочасткового
графу, хоча така процедура (а виходить, і ефективний алгоритм відшукання найбільшого
паросочитания) відома й у випадку довільного графу. Отже, нехай G = (X, Y, E) –
двочастковий граф і М – паросполучення в цьому графі. Поставимо у відповідність графу G і
паросполучення М допоміжний орієнтований двочастковий граф
G  ( X , Y , A), полагая A  A1  A2 , где A1  {( y , x) : x  X , y  Y , xy  M },
A2  {( y, x) : x  X , y  Y , xy  EG \ M }.
Іншими словами, щоб одержати графG, досить додати орієнтацію “від Y до X” усіх ребер
графа G, що входить у паросполучення М, і “від X до Y” всіх інших ребер цього графа. На
мал. 77.2 зображені граф G з паросполученням М (виділено жирними лініями) і графG.

G G
Мал. 77.2

Позначимо через XM і YM безліч ненасичених вершин, що входять, відповідно, у X і


Y. Справедливість наступного твердження очевидна.
Теорема 77.2. У графе G збільшуючийся відносно паросполучення М ланцюг існує
тоді і только тоді, коли в графеG існує (s, t)-шлях, у якого s XM, t  Y M.
НехайР – (s, t)-шлях у графі G, s  XM, t YM, P – відповідний ланцюг, що
збільшується, у ( G і М1 - паросполучення, отримане зміною М уздовж ланцюга Р. Тоді
допоміжний графG1 для графа G і паросполучення М1 можна одержати з графаG заміною
кожної дуги шляхуP на зворотню. Ця операція разом з пошуком шляхуP складає ітерацію
алгоритму, що приводиться. Передбачається, что граф G заданий списком суміжності.
Алгоритм А6 побудови найбільшого паросполучення в двочастковому графі.
1. Побудувати будь-яке максимальне паросполучення М в графі G.
2. По графі G і паросполученню М побудувати граф G.
3. Нехай у графе

G X   {x : x  X , d  ( x )  0}, Y   { y : y  Y , d  ( y )  0}
[в графе G X  Y   множество вершин, не насыщенных текущим
паросочитанием ]. Выполнить в графе G поиск в ширину ( алгоритм А6 )
из множества Х  .

4. Якщо в результаті пошуку в ширину з вершин безлічі


не одержали мітки, то перейти до п.5. Інакше перейти до п.6.
5. Нехай Т = {(x1, y1), (x2, y2), ..., (xk, yk)} – безліч усіх дуг, що виходять з безлічі Y.
Покласти М* = {y1x1, y2x2, ..., ykxk} [M* - найбільше паросполучення]. Кінець.
6.
Пусть P  ( s, t )  путь в графе G такой , что s  X  , t  Y  . Изменить граф G,
заменив в нём каждую ( a, b) пути Р на дугу (b, a ). Перейти к п.2.

Y
Теорема 77.3. Алгоритм А8 будує найбільше паросполучення в двочастковому графі
G = (X, Y, EG) за час O (|EG| min {|X|, |Y|}).
Те, що алгоритм коректний і побудоване їм паросполучення є найбільшим, випливає з
теореми 77.1 і твердження 77.2. Очевидно також, що число ітерацій алгоритму (тобто
виконань п. 2 – 5) не перевершує величини min {|X|, |Y|}, оскільки на кожній ітерації, крім
останньої, величини
| X  |и |Y  |
зменьшується на одиницю.
Відповідно до твердження 76.2 п. 3 виконується за час O(|EG|). Легко показати, що ця
ж оцінка трудомісткості справедлива і для інших кроків алгоритму. Таким чином, час
виконання окремої ітерації складає O( |EG| ), а алгоритму в цілому – O (|EG| min {|X|, |Y|}).
Разом з найбільшим паросполученням алгоритм А8 фактично знаходить і найменше
верхове покриття в графе G. У результаті останнього виконання п. 3 алгоритму буде
встановлена відсутність шляху з
X иY
у графе G. Отже, тільки частина вершин цього графа буде мати мітки після закінчення
пошуку в ширину з
X .
Позначимо через X і Y, відповідно, безлічі непомічених вершин частки Х и позначених
вершин частки Y. Покладемо Z = X + Y.
Будемо вважати, що в графе G немає ізольованих вершин.
Теорема 77.4. Безліч Z є меншим верховим покриттям графа G.
Твердження достатнє довести для зв’язаних графів. Нехай (a, b) – довільна дуга
графа(G. Якщо a(Y, b(X, то ці вершини або обидві позначені, або ні. В обох випадках дуга (a,
b) инцідентна вершині безлічі Z. Нехай a(X, b(Y. Тоді, якщо вершина не позначена, то a(Z.
Якщо ж a позначена, то і вершина b позначена і, отже, b(Z.
Отже, будь-яка дуга графа (G инцидентна деякій вершині безлічі Z, тобто Z – покриття
графа G. Крім того, легко бачити, що | Z | = | T |, де Т – безліч усіх дуг графа (G, що ведуть з
безлічі Y. Безлічі Т в графі G відповідає найбільше паросполучення. Тому з теореми 32.2
випливає, що верхове покриття Z є найменшим.
Використаний тут метод ланцюгів, що чергуються, відіграє важливу роль і при
рішенні більш загальних задач. Одну з них ми зараз розглянемо.
2. Алгоритм побудови паросполучень для зважених графів. Нехай G = (X, Y, EG) –
повний двочастковий зважений граф, | X | = | Y | = n. Потрібно знайти в графе G
паросполучення, вага якого мінімальний. Легко бачити, что це – згадувана раніше задача
про призначення (див. гл. IV, параграфа 30).
Зроблене паросполучення мінімальної ваги назвемо для стислості оптимальним
розв’язком.
Задача про призначення володіє двома простими властивостями:
1. Оскільки для кожної вершини будь-яке зроблене паросполучення містить у
точності одне ребро, инцідентне цій вершині, то безліч оптимальних рішень не
зміниться, якщо ваги всіх ребер, инцідентних якій-небудь вершині, збільшити
(зменшити) на те саме число.
2. Якщо ваги всіх ребер графа невід’ємні і вага деякого зробленого паросполучення
дорівнює нулю, то воно є оптимальним розв’язком.
Нехай, як звичайно, w(x, y) – вага ребер xy. Будемо вважати, що

w( x, y )  0 для каждого ребра xy  EG.


З першої властивості випливає, що випадок, коли маємо ребра від’ємної ваги, зводиться до
нашого. Крім того, ця властивість дозволяє, витративши
O (n 2 )
операцій, перейти до зваженого графа, у якого кожній вершині інцидентно ребро нелівої
ваги і ваги всіх ребер невід’ємні. Для цього досить змінити матрицю ваг графа G у такий
спосіб: спочатку відняти з всіх елементів кожного рядка мінімальний елемент цього рядка, а
потім то ж саме проробити зі стовпцями. Будемо вважати, что ця операція вже виконана і
граф G має необхідні властивості.
Нехай A  X, B  Y і де-яке число. Будемо говорити, що до графа G
застосовується операція (А, У, ), якщо спочатку з ваги кожного ребра, інцидентного
вершині з безлічі А, віднімається а потім до ваги кожного ребра, інцидентного
вершині з У, додається ?. Відповідно до властивості 1 зважений граф, що вийшов у
результаті, має ту ж безліч оптимальних рішень, що і граф G. Крім того, ребра виду ab, де a
 A, b  B, у перетвореному графі будуть мати ті ж ваги, что й у вихідному. Нехай T = (X,
Y, U) – двочастковий граф і М – паросполучення в цьому графі. Будемо, як і раніше,
позначати черезT = T(T, M) орієнтований двочастковий граф, отриманий із графа Т
шляхом ориентаций «від Y до X» усіх ребер паросполучення М и «від X до Y» інших ребер
цього графу.
Будемо вважати, что граф G заданий матрицею ваг.
Алгоритм А9 побудови зробленого паросполучення мінімальної ваги в
двочастковому зваженому графі.
1. Побудувати граф T = (X, Y, U), U = {xy: w(x, y) = 0}.\
2. Знайти в графі Т максимальне паросполучення М. Нехай XM і YM – безлічі
вершин, не насичених паросполученням М и вхідних, відповідно, у частки X і Y.
3. Якщо XM = YM = (, то кінець [М – оптимальний розв’язок задачі]. Інакше
побудувати граф(T = (T(T, M).
4. Застосувати до графа(T пошук у ширину (алгоритм А6) з безлічі XM. Якщо
знайдений (x, y)-шлях Р, x(XM, y( YM, то перейти до п. 5. Інакше до п. 7.
5. Перетворити графT,
замінивши в ньому кожну дугу шляху Р на зворотню. Нехай
X M  {x : x  X , d  ( x)  0}, YM  { y : y  Y , d  ( y )  0}
[шляхом зміни М уздовж ланцюга, що збільшує, знайдене нове паросполучення в T T
= (X, Y, U), XM ( X, YM ( Y - підмножини вершин Т Т, не насичених новим
паросполученням].
6. Якщо XM = YM = (, то кінець [безліч усіх таких ребер xy, x ( X, y ( Y і (y, x) – дуга
графа(Т, складає зроблене паросполучення мінімальної ваги у вихідному графі G].
Інакше перейти до п. 4.
7. Нехай X( ( X і Y( ( Y – підмножина вершин графа(Т, що одержала позначки в
результаті пошуку в ширину (у п. 4). Серед ребер графа G, що мають вид xy, x
( X(, y ( Y – Y(, знайти ребро мінімальної ваги. Нехай ??– вага цього ребра.
8. Модифікувати ваги дуг графа G, застосувавши до нього операцію (X(,Y(,().
9. Модифікувати граф(T додавши до нього всі такі дуги (x, y), що x ( X(, y ( Y – Y(,
w(x, y) = 0, і видаливши всі такі дуги (x, y), що x ( X – X(, y ( Y(. Перейти до п. 4.
Займемося тепер обґрунтуванням алгоритму А9. Корективность пп. 1 – 3 не викликає
сумнівів. Легко бачити також, что кожний з цих пунктів можна виконати за час
O ( n 2 ).
Інші пункти алгоритму розглянемо більш докладно.
Кожне виконання п. 5 збільшує на одиницю число вершин
y  Y , для которых d  ( y )  1.
Отже, цей пункт виконується не більш n раз. Наша найближча мета – показати, що після
виконання пп. 4, 6 – 9 не більш ніж n раз підряд обов'язково відбудеться перехід до п. 5.,
тобто очевидне виконання п. 4 закінчиться відшуканням шляху Р. Розглянемо докладніше
пп. 7 – 9. Після закінчення п. 4 і переходу до п. 7 кожна дуга графа(T інцидентна принаймні
одній вершині безлічі (X – X() ( Y(. Це відразу випливає з твердження 77.4. Таким чином,
кожне ребро нульової ваги в графі G інцидентно однієї з вершин цієї безлічі. З іншого боку,
оскільки XM ( (, Y M ( (, те X( ( X, Y( ( Y. Тому з правила вибору величини ??в п. 7 випливає,
що ??> 0. Після модифікації графу G у п. 8 ваги його ребер залишаться невід’ємними (це
випливає з правила вибору ?). У результаті наступної модифікації графу(T у (п. 9) володіє
двома важливими властивостями. По-перше, вилучені дуги цього графа спрямовані від
непомічених вершин частки Х. Тому усі вершини, досяжні з ХМ у “старому” графі(T
досяжні з цієї безлічі й у “новому” графі(T. По-друге, додані дуги спрямовані від позначених
вершин частки Х к непоміченим вершинам частки Y. Таким чином, застосування пошуку в
ширину до модифікованого графа(T (п. 4) приведе до того, що додатково буде позначена
принаймні одна вершина частки Y. Оскільки | Y | = n, то після виконання пп. 4, 7 – 9 не більш
ніж у n раз підряд позначеної зробить деяка вершина безлічі YM , тобто буде знайдений
шлях Р, і потім піде виконання п. 5. Як уже було показано, п. 5 (а виходить, і п. 6)
виконується не більш n раз. Тому кожний із пп. 4, 7 – 9 виконується не більш
n2
раз.
Легко бачити, что трудомісткість кожного з пп. 1 – 9 не перевершує
O ( n 2 ).
Тому час роботи алгоритму в цілому оцінюється зверху величиною
O (n 4 ).
Як відзначалося вище, після виконання п. 8 ваги всіх ребер графа G залишаються
невід’ємними, і, отже, безліч оптимальних рішень не міняється. Умові закінчення XM = YM
= ( означає, що в «останньому» графі(T мається n дуг, спрямованих від Х к Y, яким
відповідає зроблене паросполучення нульової ваги в «останньому» графі G. Відповідно до
властивості 2 воно є оптимальним розв’язкомм вихідної задачі.
Резюмуємо усе вище викладене у виді теореми.
Теорема 77.5. Алгоритм А6 будує зроблене паросполучення мінімальної ваги в
двочастковому зваженому графі G = (X, Y, | EG |), | X | = | Y | = n, за час O(n4).
Зауваження. Відомий алгоритм, що вирішує цю задачу за час O(n3).
В алгоритмі А6 оцінка O(n4) виникає, власне кажучи, через те, що приходиться O(n2)
раз виконають операцію (X, Y, ), що сама вимагає часу O(n2). Зниження оцінки до O(n3)
досягається за рахунок того, що результат цієї операції вдається одержати за час O(n).
Недавно опублікований алгоритм, оцінка трудомісткості якого в багатьох випадках
переважніше O(n3). Ця оцінка має вид O(n2,5log(n)), де Т – найбільший з ваг ребер графа.

2 0* 0 0 0
0 * 7 9 8 6

0 1 3 2 2
 
0 8 7 6 4
 0 7 6 8 3

мал. 77.3

Приклад. На мал. 77.3 представлена матриця ваг W = || Wij || двочасткового графа G =


(X, Y, EG), у якої Wij = w(xi, xj), xi ( X, xj (Y.
Там же зображений граф(T, побудований по максимальному паросочитанию M = {x2y1,
x1y2} нульові ваги в графі G. Відповідні цьому паросочитанию дуги графа(T обведені
жирними лініями, а елементи матрици W відзначені зірочками.
Перед першим виконанням п. 4 маємо XM = {x3, x4, x5}, YM = {y3, y4, y5}. Пошук у
ширину з XM дає Х' = {x2, x3, x4, x5}, У' = {y1}. Вершини безлічі X( ( Y( будемо відзначати
значком «+». Оскільки шляху з XM у YM немає, те переходимо до пп. 7 – 9. Знаходимо ??=
W32 = 1 і не виконуємо операцію ({x2, x3, x4, x5}, {y1}, 1), тобто віднімаємо 1 із всіх
елементів у рядках 2, 3, 4, 5 і додаємо це число до всіх елементів першого стовпця. У
результаті до графа(T додасться дуга (x3, y2). Модифікована матриця W (тобто граф G) і
граф(T представлені на мал. 77.4 застосування пошуку в ширину до графа(T дає шлях Р =
(x3, y2, x1,y5) з XM у YM. Замінимо (виконання п. 5) у графі(T дуги (x3, y2), (y2, x1), (x1,y5)
відповідно на дуги (y2,x3), (x1, y2), (y5, x1). Новий граф(T також зображений на мал. 77.4. У
ньому XM = {x4, x5}, YM = {y3, y4}.
Знову виконавши пошук у ширину з XM, одержимо X’ = {x2, x4, x5}, Y’ = {y1}.
Серед елементів матрици W, що лежать на перетині рядків з номером 2, 4, 5 і стовпцем з
номерами 2, 3, 4, 5, знаходимо мінімальний.

3 0 0 0 0 *
0 * 6 8 7 5 

0 0* 2 1 1
 
0 7 6 5 3
 0 6 5 7 2 
Мал. 77.4

5 0 0 0* 0
0 * 4 6 5 3 

2 0* 2 1 1
 
0 5 4 3 1
 0 4 3 5 0 *

Мал. 77.5

6 0 0 0* 0
0 * 3 5 4 2 

3 0* 2 1 1
 
0 4 3 2 0
 1 4 3 5 0 *

Мал. 77.6
Одержимо ??= W32 = 2. Результати наступного застосування до графа G операції ({x2, x4,
x5}, {y1}, 2) і модифікований граф(T, представлені на мал. 77.5. У цьому графі мається шлях
Р = (x5, y5, x1, y4) із з XM у YM. «Новий» граф(T, отриманий у результаті виконання п. 5,
також зображений на мал. 77.5. Пошук у ширину в цьому графі з безлічі XM = {x4} дає Х' =
{x2, x4}, У' = {y1}. Знаходимо ??= W32 = 1. Результати наступного виконання пп. 8, 9
представлені на мал. 77.6. Пошук у ширину з x4 дає Х' = {x2, x4, x5}, Y '= {y1, y5}.
Знаходимо ??= W32 = 2. Одержуємо нові матрицю і граф(T (мал. 77.7). У графі(T маємо (x4,
y3)-шлях Р = (x4, y4, x1, y3). Змінивши цей граф відповідно до п. 5, одержимо новий (мал.
77.7), у якому XM = YM = (.
П'ять его дуг, що ведуть «від X до Y», відповідають ребрам зробленого паросполучення
мінімальної ваги у вихідному графі G. Вага цього

8 0 0* 0 2
0 * 1 3 2 2 

5 0* 2 1 3
 
0 2 1 0* 0
 1 2 1 3 0 *

мал. 77.7

паросполучення дорівнює 0 + 0 + 0 + 1 + 6 + 3 = 10.

You might also like