Вы находитесь на странице: 1из 8

Алгоритмы

ДЗ 7
Халилов Арслан
Б05-223
22 мая 2023 г.

Задача 1
Будем использовать модифицированный алгоритм Крускала.

1. Отсортируем все ребра графа по неубыванию веса.

2. Заведем СНМ для управления ребрами и вершинами.

3. Введем cnt - количество ребер, которые нужно добавить до дости-


жения 78 n, где n - количество вершин графа, и счетчик добавленных
ребер.

4. Пройдемся по отсортированным ребрам, и для каждого ребра про-


верим, объединяет ли он два разных множества в СНМ. Если объ-
единяет, добавим его в минимальный остов и увеличим cnt. Если
cnt достиг 78 n - остановим цикл.

5. Ура!

Время работы этого алгоритма составляет O(n + m), так как сорти-
ровка ребер занимает O(m · log(m)) (но в данном случае, m = O(n) ),
итерация по ребрам занимает O(m), и операции СНМ занимают O(α(n))
почти каждый раз, где α(n) - функция обратного Аккермана, которая
растет очень медленно и практически может быть считана константой.
Мы сравниваем O(n + m) со всеми этими операциями, в итоге асимпто-
тическая сложность остается O(n + m).

1
Задача 2
Для решения этой задачи мы можем использовать алгоритм Куна с неко-
торыми оптимизациями. Вот основные шаги алгоритма:

1. Отсортируем вершины левой доли по возрастанию значения li . Это


потребует O(n · log(n)) времени.

2. Используем модифицированный алгоритм Куна с "жадным"стартовым


поиском, выполняющего попытку обработать все вершины правой
доли из отрезков [li , ri ] сначала без использования дополнительных
паросочетаний.

Алгоритм Куна
1. Создаем вектор ‘matching‘ размером равным количеству вершин в
правой доли, заполненный нулями.

2. Для каждой вершины i левой доли выполняем функцию ‘tryMatching‘:

• Если вершина i не была обработана, проверяем каждую вер-


шину из отрезка [li , ri ].
• Если вершина правой доли еще не соединена с другой вер-
шиной (то есть значение ‘matching‘ равно 0), соединяем ее с
вершиной i.
• Если вершина правой доли уже соединена с другой вершиной
(которую мы обозначим как j), но для вершины j есть другая
вершина (например, k) с меньшим номером из отрезка [lj , rj ],
такая что вершина k может быть подключена к вершине j,
переподсоединяем вершину правой доли к вершине k и про-
должаем исследование возможных паросочетаний с вершиной
k. Если нет такой вершины k, передвигаемся к следующей вер-
шине в отрезке [li , ri ].
• Повторяем шаг 2 до тех пор, пока не обработаем все вершины
левой доли.
• В конце алгоритма, подсчитываем количество ненулевых эле-
ментов в векторе ‘matching‘. Это количество элементов будет
равно размеру максимального паросочетания.

2
Время, затраченное на алгоритм Куна, равно O(n · k), где k - коли-
чество вершин правой доли и n - количество вершин левой доли. Од-
нако из-за сортировки вершин левой доли и "жадного"подхода, практи-
ческое время выполнения этой модификации алгоритма будет ближе к
O(n · log(n)).

Задача 3
Докажем утверждение по индукции на длине максимального пути в ато-
графе.

База
Если размер длинного пути = 1, то мы имеем только один путь, состоя-
щий из двух вершин и двух дуг (a, b), (b, c). Здесь нам нужно два неза-
висимых множества {a, c} и {b} для разбиения вершин. Доказательство
утверждения очевидно верно для базы.

Шаг индукции
Предположим, что утверждение верно для всех атографов с длиной мак-
симального пути n. Докажем утверждение для атографов с длиной мак-
симального пути n + 1.
Пусть G - атограф с максимальной длиной пути n+1. Удалим верши-
ну b, находящуюся в длиннейшем пути и имеющую наибольшую степень
исхода (если таких вершин несколько, выберем любую из них). Обозна-
чим полученный граф как G′ . С учетом транзитивности, на максималь-
ном пути, содержащем b, все предыдущие вершины до b имеют ребра к
следующим вершинам после b (дуги, исходящие из предыдущих вершин
до b, также направлены к вершинам после b). Это означает, что длина
максимального пути в G′ равна n.
Теперь для этого графа G′ по предположению индукции существует
разбиение на независимые множества A1 , A2 , . . . , An . Вернем вершину b
в граф, получив изначальный граф G. Теперь разобьем вершины G на
независимые множества следующим образом:

1. Вершины из A1 остаются в A1 .

2. Вершины из A2 остаются в A2 .

3. . . .

3
4. Вершины из An остаются в An .

5. Вершина b будет добавлена в множество An+1 .

Таким образом, мы разбили вершины графа G на n + 1 независимых


множеств. Теперь нам нужно доказать, что такое разбиение действитель-
но минимально.
Предположим, что есть более хорошее разбиение H на m независи-
мых множеств, где m < n + 1. Тогда для некоторой пары вершин a и
c в множестве H (допустим, a и c находятся в Hj и Hk соответствен-
но, где j ̸= k), вершины a и являются несоседними, и существуют дуги
(a, b), (b, c) в G. Однако, это противоречит транзитивности атографа, так
как должна была быть также и дуга (a, c), что делает a и c соседними, а
значит, они не могут быть в разных независимых множествах Hj и Hk .
Значит, наше предположение о существовании такого разбиения невер-
но, и наименьшее количество независимых множеств, на которые можно
разбить все вершины G, равно размеру самого длинного пути в G, то
есть n + 1.
Итак, по принципу математической индукции, изначальное утвер-
ждение верно для всех ациклических транзитивных орграфов.

Задача 4
а)
Докажем, что первый игрок выигрывает, если стартовая вершина лежит
во всех максимальных паросочетаниях.
В начале игры допустим, максимальное паросочетание содержит стар-
товую вершину s. Первый игрок может передвинуть фишку вдоль паро-
сочетанного ребра к вершине t. Теперь у, находясь в вершине t, игроки
имеют меньший граф с вершинами, до которых они еще не дошли. Если
в этом подграфе есть максимальное паросочетание, то вся игра продол-
жается. Но если максимальное паросочетание содержит s, то в подгра-
фе максимальное паросочетание будет содержать на одно ребро меньше.
Значит, первый игрок будет выигрывать, так как в конечном итоге вто-
рой игрок не сможет сделать ход.
Теперь докажем в другую сторону. Если стартовая вершина s не ле-
жит в одном из максимальных паросочетаний, то максимальное паро-
сочетание в графе содержит четное число ребер. Когда первый игрок
делает ход, они оказываются в ситуации с максимальным паросочета-
нием, содержащим нечетное число ребер, и, таким образом, ситуацию

4
меняется на второго игрока, который сталкивается с максимальным па-
росочетанием счетным числом ребер, и так далее. В итоге первый игрок
проигрывает, так как не может сделать ход в определенный момент.

б)
Рассмотрим алгоритм для определения выигрыша вершины в двудоль-
ном графе G.
1. Найдем максимальное паросочетание в G. Мы можем использовать
алгоритм Куна, который выполняется за время O(n · m).
2. Для каждой вершины u проверяем, лежит ли она в найденном мак-
симальном паросочетании. Если нет, то вершина u является выиг-
рышной стартовой вершиной, и мы дополнительно должны сохра-
нить этот результат. Если вершина u лежит в максимальном па-
росочетании, то следует удалить эту вершину и ее паросочетанное
ребро из графа и искать максимальное паросочетание в оставшемся
графе. Затем восстановим вершину u и исключим следующую вер-
шину. В итоге посещаем каждую вершину и ищем максимальные
паросочетания после удаления каждой из них. Это займет O(n2 ·m).
Однако, можно улучшить алгоритм до O(n · m), если после удале-
ния вершины u из графа вместо поиска максимального паросочетания с
нуля для полученного графа, мы попытаемся восстановить максималь-
ное паросочетание с уже известной пары. Для этого нужно использо-
вать идею аугментирующих цепей. После удаления ребра, нужно найти
аугментирующую цепь, которая позволит заменить удаленное ребро на
новое, чтобы вернуть паросочетание к максимальному состоянию.
При использовании алгоритма Куна, можно провести DFS по уда-
ленной вершине и поставить запрет на проход по удаленным ребрам.
Если находим аугментирующую цепь, значит, стартовая вершина была
частью максимального паросочетания, и наш путь предоставляет изме-
ненное максимальное паросочетание. Если же аугментирующая цепь не
найдена, стартовая вершина победит.
В итоге мы получаем O(n · m) для определения всех вершин графа,
как потенциально выигрышных стартовых вершин.

Задача 5
Для решения этой задачи мы будем использовать алгоритм поиска па-
росочетания в двудольном графе. Перед тем, как решать задачу, раз-

5
двоим вершины. Для каждой вершины v создадим две новые вершины:
vin и vout . Затем заменим каждое ребро (u, v) на два ребра: (uout , vin ) и
(vout , uin ).
Теперь построим двудольный граф на этих новых вершинах. Левая
доля у нас будет состоять из вершин вида vin , а правая доля - из вершин
vout . Ребра также уже определены после раздвоения вершин.
Теперь применим алгоритм нахождения максимального паросочета-
ния для этого двудольного графа. Если найденное максимальное паросо-
четание покрывает все вершины графа (то есть, каждая вершина имеет
пару), то можно сказать, что такое множество циклов существует.
Если множество циклов найдено, то мы можем восстановить их с
помощью паросочетания. Для этого пройдемся по паросочетанию и вос-
создадим путь в исходном графе из vin в uout по ребру, и затем из uout в
vin .
Асимптотика составит O(n · m), так как это является сложностью ал-
горитма поиска максимального паросочетания в двудольном графе (на-
пример, используя алгоритм Хопкрофта-Карпа). В результате, решение
соответствует заданной асимптотике.

Задача 6
Примечание: я не очень понимаю как в латехе делать enumerate по рус-
ским буквам, по этому тут вместо (а, б, в) будет (a, b, c)..

Будем использовать алгоритм Хопкрофта-Карпа, который находит мак-


симальное паросочетание в двудольном графе за O(n · m).

1. Сначала мы найдем максимальное паросочетание M с помощью


алгоритма Хопкрофта-Карпа в графе G.
2. Затем проверим каждое ребро (u, v) и определим, к какой из кате-
горий оно относится:

a) Ребро (u, v) может лежать в максимальном паросочетании, ес-


ли после удаления этого ребра из графа и определения макси-
мального паросочетания в полученном графе, размер паросо-
четания не уменьшается.
b) Ребро (u, v) обязано лежать в максимальном паросочетании,
если после удаления этого ребра из графа и определения мак-
симального паросочетания в полученном графе, размер паро-
сочетания уменьшается на 1.

6
c) Ребро (u, v) не может лежать в максимальном паросочетании,
если оно не принадлежит ни одному из максимальных паро-
сочетаний в графе.

3. Для определения категории каждого ребра (u, v), итерация будет


работать O(m). После каждой итерации снова вычисляем макси-
мальное паросочетание с помощью алгоритма Хопкрофта-Карпа за
время O(n · m), что в сумме дает нам O(n · m2 ).

Это не совсем удовлетворяет условию O(n · m), однако мы можем опти-


мизировать алгоритм следующим образом:

1. Используя алгоритм Хопкрофта-Карпа, найдем максимальное па-


росочетание M в графе G.

2. Обозначим H как граф, полученный добавлением обратных ребер


к каждому ребру из паросочетания M . Теперь задача сводится к
поиску вершин, которые достижимы от вершин непокрытой части
доли графа G по графу H.

3. Используя поиск в глубину или в ширину, найдем все вершины,


достижимые от непокрытых вершин из левой доли G в графе H.

4. Теперь проверим каждое ребро (u, v) и определим его категорию:

a) Ребро (u, v) может лежать в максимальном паросочетании, ес-


ли оно принадлежит графу H, и в результате поиска в глубину
(или в ширину) вершины u и v были помечены как достижи-
мые от других непокрытых вершин доли G.
b) Ребро (u, v) обязано лежать в максимальном паросочетании,
если оно текущей паросочетании M , и вершины u и v не были
достижимыми при поиске в глубину (или в ширину) на шаге
3.
c) Ребро (u, v) не может лежать в максимальном паросочетании,
если оно не удовлетворяет условиям для категорий "а"или "б".

Выполнение алгоритма Хопкрофта-Карпа занимает время O(n · m), а


дополнительные шаги с использованием поиска в глубину или в ширину
требуют времени O(n + m). Таким образом, общая сложность алгоритма
составляет O(n · m).

7
Задача 7
Для решения этой задачи можно использовать следующий алгоритм:

1. Найдите все связные компоненты из незаблокированных клеток


таблицы. Для этого можно использовать DFS. Запомните для каж-
дой компоненты её размер. Время выполнения: O(n · m).

2. Для каждой связной компоненты проверьте, можно ли разбить её


на циклические маршруты длины хотя бы 3. Это возможно, если
размер компоненты делится на 3 и размер больше или равен 3. Если
хотя бы для одной компоненты это условие не выполняется, ответ
будет "нельзя". В противном случае ответ будет "можно". Время
выполнения: O(k), где k - число связных компонент.

Суммарное время выполнения алгоритма: O(n · m).


Примечание: если размер связной компоненты кратен 3 и больше или
равен 3, то возможный маршрут может быть найден, например, при
помощи "змеевидного"обхода компоненты с образованием циклов по 3
клетки.

Вам также может понравиться