Графы#

Если вдруг все дороги ведут в никуда, значит, пора возвращаться домой…

Возможно, самое распространенное применение графов — это описание сетей. Точки сети — это узлы графа, а связки — ребра между ними. Существует большое количество разных видов сетей; в первую очередь компьютерные сети, где все компьютеры соединены друг с другом, тут же и транспортные сети, которые с помощью автомагистралей, авиа- и железнодорожных путей соединяют друг с другом города. В плане компьютерных сетей самым ярким примером будет Интернет, да и название Сеть говорит само за себя: она состоит из страниц-узлов, соединенных друг с другом гиперссылками. «Википедия» — особо огромная сеть, разновидность глобальной Сети. Если заглянуть в область электроники, электросхемы состоят из электротехнических компонентов, таких как транзисторы, соединенных цепями. В биологии мы встречаем метаболические сети, которые, помимо прочего, содержат метаболические пути: химические вещества связаны химическими реакциями. Социальные сети представлены как графы, в которых узлами являются люди, а ребрами — их отношения. Распределение работы между людьми и машинами тоже можно смоделировать с помощью графов: задания — это узлы, а взаимосвязи между ними, например распределение приоритетов заданий, можно считать ребрами. (Луридас - Алгоритмы для начинающих)

Основные понятия#

Источник: лекции ВМК МГУ

Пусть задано конечное множество \(V = \{v_1, v_2, \ldots, v_n\}\) - вершины графа. Некоторые (неупорядоченные) пары вершин соединяются рёбрами, все рёбра образуют множество \(E = \{e_1, e_2, \ldots, e_m\}\), где \(e_k = \{v_i, v_j\}\).

Графом называется пара множеств: вершин и рёбер, то есть \(G = \langle V, E \rangle\).

Поскольку число различных неупорядоченных пар, выбранных из множества с \(n\) элементами, равно \(C_n^2 = \dfrac{n(n-1)}{2}\), то максимальное число рёбер в графе равно \(\dfrac{n(n-1)}{2}\).

Пример. На рисунке представлен граф с 7 вершинами и 5 рёбрами.

\(V = \{v_1, v_2, \ldots, v_7\}\)

\(E = \{e_1 = \{v_1, v_2\}, e_2 = \{v_2, v_4\}, e_3 = \{v_3, v_4\}, e_4 = \{v_3, v_1\}, e_5 = \{v_5, v_6\}\}\)

Ориентированным графом называется пара множеств: вершин и ориентированных рёбер. Ориентированное ребро - это упорядоченная пара вершин графа.

Пример. Если в предыдущем примере считать все пары упорядоченными, то получится такой орграф.

\(V = \{v_1, v_2, \ldots, v_7\}\)

\(E = \{(v_1, v_2), (v_2, v_4), (v_3, v_4), (v_3, v_1), (v_5, v_6)\}\)

С помощью графа мы задаём структуру связей между элементами. Так, в компьютерной сети информацию можно передать между узлами по каналам связи, которые моделируются рёбрами графа.

Граф с кратными рёбрами называют мультиграфом. Если, помимо кратных рёбер, допускаются и петли, получается псевдограф. Таким образом, в мультиграфе множество рёбер является мультимножеством, а в псевдографе в качестве рёбер выступают и пары одинаковых вершин.

Путь в графе - это чередующаяся последовательность вершин и рёбер этого графа \(v_{i_1} \; e_{i_1} \; v_{i_2} \; e_{i_2} \; v_{i_3} \; \ldots\), в которой каждое ребро соединяет соседние с ним вершины.

Пример. В приведенном ориентированном графе допускается такой маршрут: \(v_3 \; (v_3, v_1) \; v_1 \; (v_1, v_2) \; v_2 \; (v_2, v_4) \; v_4\).

Если путь состоит из вершин \(v_1, v_2, \ldots, v_l\), причём начальная вершина совпадает с конечной, то есть \(v_1 = v_l\), то это замкнутый путь. Если в замкнутом пути вершины не повторяются, его называют циклом.

Связность графа#

Рассмотрим неориентированный граф.

Граф называется связным, если между любой парой его вершин существует путь.

Связная компонента графа - это максимальный по включению (вершин и рёбер) связный подграф.

Чтобы уточнить понятие связности, введем на множестве вершин графа отношение достижимости \(\rho\). Пара вершин \((v_i, v_j)\) принадлежит отношению \(\rho\) (т.е. \(v_i \rho v_j\)), если существует путь из \(v_i\) в \(v_j\).

Упражнение. Докажите, что отношение достижимости рефлексивно, симметрично и транзитивно.

Итак, \(\rho\) является отношением эквивалентности.

Следовательно, всё множество вершин разбивается на классы эквивалентности - это и есть связные компоненты.

Утверждение. В связном графе \(|E(G)| \geq |V(G)| - 1\).

Доказательство. Проведем доказательство методом математической индукции по числу вершин графа. Докажем, что в любом связном графе с \(n\) вершинами справедливо \(|E| \geq n - 1\). База индукции: при \(n = 1\) доказывать нечего. Гипотеза индукции: допустим, что утверждение доказано для \(n = k\). Шаг индукции: рассмотрим граф с \(n = k + 1\) вершинами и докажем, что \(|E| \geq k\). Уберём из графа \(n\)-ю вершину вместе со всеми исходящими из неё ребрами. Получим граф \((V', E')\), в котором хотя бы на одно ребро меньше, и в нём \(k\) вершин. Значит, для этого графа \(|E'| \geq k - 1\). Следовательно, для графа \((V, E)\) выполнено неравенство \(|E| \geq |E'| + 1 \geq (k - 1) + 1 = k\). Утверждение доказано.

Утверждение. Для любого графа \(G\) выполняется неравенство:

\(|E(G)| - |V(G)| + |C(G)| \geq 0\),

где \(V(G)\) - множество вершин, \(E(G)\) - множество рёбер, \(C(G)\) - множество связных компонент.

Число в левой части неравенства называется цикломатическим числом графа.

Доказательство. Разберём сначала случай связного графа, в котором \(|C(G)| = 1\). В этом графе число рёбер не меньше, чем число вершин без единицы, т.е. \(|E(G)| \geq |V(G)| - 1\).

Теперь рассмотрим общий случай. Для каждой связной компоненты \(G'\) графа \(G\) выполняется неравенство \(|E(G)| - |V(G)| + 1 \geq 0\). Суммируя эти неравенства по всем связным компонентам графа, приходим к требуемому неравенству.

Степени вершин#

Источник: Вялый и др. - Лекции по дискретной математике

Рассмотрим неориентированный граф.

Степень вершины - это число смежных с этой вершиной рёбер.

Будем обозначать степень вершины \(u\) через \(\mathrm{deg}(u)\). По определению,

\( \mathrm{deg}(u) = |\{ v \in V \colon \{u, v\} \in E \}| \)

Эта запись означает: степень вершины \(u\) равна мощности множества вершин графа \(v\), которые соединены ребром с \(u\).

Лемма (о рукопожатиях). В неориентированном графе \(G\) сумма степеней всех вершин равна удвоенному числу рёбер:

\( \sum\limits_{v \in V} d(v) = 2|E| \)

Доказательство. Рассуждаем по индукции. Будем проводить в графе ребро за ребром. Пусть на \(k\)-шаге оказалось, что сумма степеней вершин равна удвоенному числу шагов \(2k\). Сделаем ещё один шаг. Так как рёбра в графе не повторяются, при добавлении одного ребра общее число рёбер в графе увеличивается на \(1\). При этом степени ровно двух вершин увеличатся на 1. Таким образом, к левой и правой части равенства будет прибавлено число \(2\), следовательно, равенство остается верным.

Следствие. В любом неориентированном графе число вершин, имеющих нечетную степень, чётно.

Упражнение. Докажите, что в любом графе с более чем одной вершиной есть две вершины одинаковой степени.

Задача. На контрольной каждый из 20 школьников решил ровно 3 задачи, а каждую задачу решило ровно 5 человек. Сколько было задач?

Построим двудольный граф (доля школьников и доля задач), в котором каждая из 20 вершин первой доли соединена ровно с 3 вершинами второй доли, а каждая вершина из второй доли соединена ровно с 5 вершинами первой доли.

Заметим, что в двудольном графе сумма степеней вершин первой доли равна сумме степеней вершин второй доли. Обозначив пеизвестное число вершин второй доли через \(x\), приходим к уравнению \(20 \cdot 3 = 5x\). Отсюда \(x = 12\). Значит, число задач равно 12.

Упражнение. В компании из 6 человек некоторые знакомы друг с другом (это симметрично: если А знаком с Б, то и Б знаком с А). Докажите, что можно выбрать трёх человек, которые либо попарно знакомы (все три пары), либо попарно незнакомы (все три пары).

Двудольные графы#

Источник: Вялый и др. - Лекции по дискретной математике

Двудольный граф с долями \(L\) и \(R\) - это граф с множеством вершин \(V = L \cup R\), где \(L \cap R = \varnothing\), в котором всякое ребро соединяет вершину из левой доли \(L\) с вершиной из правой доли \(R\). Итак, всякое ребро двудольного графа соединяет левую долю с правой.

Например, левая доля - студенты, правая доля - учебные курсы. Вершины (студент и курс) соединены ребром, если студент прослушал соответствующий курс.

Другой пример: левая доля - кавалеры, правая доля - дамы. Ребро означает, что они танцевали друг с другом.

Ещё пример: левая доля - остановки, правая доля - маршруты автобусов. Путь в таком графе между двумя остановками - это возможность проехать между ними на автобусе (возможно, с пересадками).

Задача. Дан произвольный неориентированный граф. Как раскрасить его вершины в два цвета так, чтобы никакое ребро не соединяло пару вершин одного цвета? (Как сделать граф двудольным?)

Алгоритм раскраски. Начнём с любой вершины графа, начнём обход графа (в глубину или в ширину). При прохождении по всякому ребру меняем цвет вершины на противоположный. Если оказалось, что какое-нибудь ребро соединяет две вершины одного цвета, то значит, искомой раскраски не существует.

Теорема. Раскраска графа в два цвета возможна тогда и только тогда, когда в графе нет циклов нечётной длины.

\(\Rightarrow\): Если в графе есть цикл нечётной длины, то его нельзя раскрасить: проходя по циклу, получим противоречие. (Например, вершины треугольника нельзя раскрасить так, чтобы концы любого ребра были разного цвета.)

\(\Leftarrow\): Предположим, что циклов нечётной длины нет. Выберем некоторую вершину \(a\) и решим, что она белая. Для любой другой вершины \(b\) посмотрим, сколько рёбер в пути от \(a\) к \(b\).

Лемма. Пусть в графе нет циклов нечётной длины. Тогда если есть два пути из \(a\) в \(b\), то либо в обоих чётное число рёбер, либо в обоих нечётное.

Доказательство леммы. Если есть путь \(a \to b\) с чётным числом рёбер, а также другой путь \(a \to b\) с нечётным числом рёбер, то в графе есть цикл с нечётным числом рёбер. Действительно, можно пройти из \(a\) в \(b\) по первому пути и вернуться по второму. Таким образом, это противоречит предположению, что в графе нет циклов нечётной длины. Значит, такого быть не может.

Доказанная лемма позволяет разбить все вершины на 2 класса по чётности длины пути от выбранной вершины \(a\). Требуемая раскраска построена.

Упражнение. Всякое ли дерево можно раскрасить в два цвета?

Степенные последовательности#

Источник: Свами, Тхуласираман - Графы, сети и алгоритмы (с. 157)

Последовательность степеней всех вершин графа называется степенной последовательностью этого графа.

Хакими и Гавел предложили алгоритм построения графа (если он существует), имеющего заданную последовательность степеней.

Алгоритм Хакими. Пусть \(d_1 \geq d_2 \geq \ldots \geq d_n\) - последовательность неотрицательных целых чисел. Уберём \(d_1\), соединив вершину \(v_1\) рёбрами с вершинами \(v_2, v_3, \ldots, v_{d_1 + 1}\). При этом числа \(d_2, d_3, \ldots, d_{d_1 + 1}\) уменьшатся на \(1\). Если при уменьшении получается отрицательное число либо последовательность обрывается - то искомого графа не существует. Иначе продолжаем процесс для получившейся последовательности (упорядоченной по убыванию). Когда вся последовательность обнулится, алгоритм завершается.

Сложность алгоритма Хакими составляет \(O(N^2)\), где \(N\) - число вершин в графе.

Упражнение. Постройте любой граф по степенной последовательности \(2, 2, 3, 3, 1, 1\).

Вычисление отношения достижимости#

Поскольку отношение достижимости получается в результате объединения всех степеней отношения, задаваемого графом, для вычисления отношения достижимости можно применить алгоритм Флойда нахождения транзитивного замыкания отношения.

\(E^* = \mathrm{id}_V \cup E \cup E^2 \cup E^3 \cup \ldots \cup E^k \cup \ldots\)

Смысл этой формулы в следующем. Чтобы понять, какие вершины достижимы одна из другой, следует сначала взять все пары вершин, достижимых за \(0\) шагов (т.е. все пары \(\mathrm{id}_V = \{(v, v)\colon v \in V\}\)). Дальше добавить к ним все пары вершин, между которыми можно пройти за \(1\) шаг (т.е. все вершины, соединенные ребром - множество \(E\)). Затем добавить все пары вершин, между которыми можно пройти за одну “пересадку” (т.е. \(E^2\)) и т.д.

(см. Хаггарти - Дискретная математика для программистов, с. 178)

Алгоритм Флойда генерирует последовательность матриц \(W_0 = M, \; W_1, W_2, \ldots, W_n\), причем элемент матрицы \(W_k\) (\(k \geq 1\)), стоящий на пересечении \(i\)-й строки и \(j\)-го столбца \(W_k(i, j)\), равен \(1\) в том и только том случае, когда существует путь (произвольной длины) из вершины \(v_i\) в вершину \(v_j\) с внутренними вершинами из множества \(v_1, v_2, \ldots, v_k\).

Матрица \(W_0\) совпадает с матрицей смежности \(M\) графа, а \(W_n\) - искомая матрица достижимости \(M^*\). Последовательные проходы цикла for вычисляют матрицы \(W_1, W_2, \ldots, W_n\).

Алгоритм Флойда (вычисление транзитивного замыкания).

\(W := M\)

for \(k = 1\) to \(n\) do

    for \(i = 1\) to \(n\) do

        for \(j = 1\) to \(n\) do

            \(W(i, j) \leftarrow W(i, j) \vee (W(i, k) \land W(k, j))\)

За каждый проход цикла (пронумерованный индексом \(k\)) алгоритм Флойда генерирует матрицу \(W_k\), используя элементы предыдущей матрицы \(W_{k-1}\).

Чтобы найти \(i\)-ую строку матрицы \(W_k\), нам следует вычислить выражения:

\(W_{k-1}(i, j) \text{\textbf{ или }} (W_{k-1}(i, k) \text{\textbf{ и }} W_{k-1}(k, j))\)

Топологическая сортировка#

Источник: Хаггарти - Дискретная математика для программистов (с. 174)

Рассмотрим ориентированный, ациклический граф.

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

Выделим в этом отношении все минимальные элементы - это вершины графа, в которые не входит ребро. Уберём из графа все минимальные элементы вместе с исходящими из них рёбрами. Запишем все удалённые вершины друг за другом. Повторим эту процедуру, продолжая запись вершин в конец полученной последовательности, пока вершины не закончатся. Это и есть алгоритм топологической сортировки.

Упражнение. В таблице приведен список действий по приготовлению цыпленка с расставленными приоритетами. Нарисуйте орграф. Упорядочите список согласно приоритетам.

Задания

Предварительные действия

А

Добавить лук к цыпленку

И

Б

Вымыть салат-латук

Л

В

Приготовить салатную заправку

Л

Г

Перемешать жаркое

К

Д

Перемешать салат

Б, В

Е

Разрезать цыпленка

никаких

Ж

Растереть имбирь

И

З

Подать готовое блюдо

И

И

Замариновать цыпленка

Е

К

Поставить казанок на огонь

А, Ж, З, Л

Л

Приготовить рис

никаких

Взвешенные графы#

Предположим, что на множестве рёбер задана числовая функция \(d \colon E \to \mathbb R\), сопоставляющая всякому ребру число - его вес. Тройка \((V, E, d)\) называется взвешенным графом.

длина кратчайшего пути

аксиомы метрики

алгоритм Дейкстры

Деревья#

Дерево - это связный, ациклический граф.

Утверждение. Граф является деревом тогда и только тогда, когда между любой парой его вершин существует ровно один путь.

\(\Rightarrow\): Предположим, что между вершинами \(a\) и \(b\) существует два пути. Но тогда объединение этих путей образует цикл. Противоречие.

\(\Leftarrow\): Допустим, что в графе между каждой парой вершин существует ровно один путь, но граф не является деревом. Тогда в графе существуют циклы. Значит, между двумя вершинами есть два пути, их соединяющих. Противоречие.

Утверждение. Дерево с \(n\) вершинами имеет \(n-1\) ребро.

Доказательство. По индукции. Допустим, что для любого дерева с \(|V| \leq k\) утверждение доказано. Докажем утверждение в случае \(|V| = k+1\). Возьмём любое ребро в дереве с \(k+1\) вершинами. При удалении этого ребра дерево распадается на два поддерева, в каждом из которых не более \(k\) вершин. В одном поддереве с \(n_1\) вершинами будет \(n_1-1\) рёбер, в другом поддереве с \(n_2\) вершинами будет \(n_2-1\) рёбер. Значит, всего в дереве \((n_1-1) + (n_2 - 1) + 1 = (n_1 + n_2) - 1 = (k + 1) - 1\) рёбер, что и требовалось доказать.

Упражнение. Докажите, что при удалении из графа любого ребра, не входящего ни в один цикл, граф теряет свойство связности.

Эйлеровы циклы#

Эйлеров цикл - это замкнутый путь, проходящий по всем рёбрам графа (по одному разу).

Пример. Задача о кёнигсбергских мостах. Можно ли обойти все мосты по замкнутому пути, пройдя по каждому мосту только раз, вернувшись в исходную точку?

Задача сводится к непрерывному росчерку линий графа.

Теорема. Необходимым и достаточным условием существования эйлерова цикла является чётность всех степеней вершин графа.

< алгоритм построения эйлерова цикла >

Пример (коды Грея). Можно ли перечислить в виде круговой последовательности все двоичные коды длины \(n\) так, чтобы каждый следующий код отличался от предыдущего ровно одной цифрой?

Представим все \(2^n\) двоичных кодов в виде графа. Ребро соединяет два кода, если они отличаются только одной цифрой. Таким образом, степень каждой вершины равна \(n\). Значит, задача имеет решение при любом чётном \(n\) и не имеет решения при нечётном \(n\).

Планарные графы#

Алгоритм Прима#

 # \(G = (V, E)\) - исходный граф

\(\sqsupset \, u_0 \in V\) - произвольная вершина

\(V' \leftarrow \{u_0\}; \;\; E' \leftarrow \varnothing\)

for \(k \leftarrow 1..|V|-1\):

    # Найти не присоединенную (ещё) вершину,

    # ближе всего лежащую к одной из присоединенных

    \((u_k, v_k) = \mathrm{argmin}\, \{ d(u, v) \colon (u, v) \in (V' \times (V \setminus V')) \cap E \}\)

    # Присоединить вершину \(v_k\) к ближайшей присоединенной

    \(V' \leftarrow V' \cup \{v_k\}\)

    \(E' \leftarrow E' \cup \{(u_k, v_k)\}\)

 # \((V', E')\) - минимальное остовное дерево графа \(G\)

Доказательство корректности алгоритма#

Проведем доказательство по индукции. Докажем следующее утверждение.

На любом \(k\)-м шаге алгоритма (\(k = 0..|V|-1\)) построенное дерево \(G' = (V', E')\) содержится (является подграфом) в некотором минимальном остовном дереве графа \(G\).

База индукции. При \(k = 0\) граф \(G' = (V', E')\), где \(V' = \{u_0\}\), \(E' = \varnothing\), очевидно, является подграфом любого остовного дерева графа \(G\).

Гипотеза индукции. Предположим, что наше утверждение истинно на \((k-1)\)-м шаге алгоритма (\(k \in 1..|V|-1\)).

Шаг индукции. Докажем тогда, что утверждение истинно на \(k\)-м шаге.

Пусть \(T\) - любое минимальное остовное дерево графа \(G\), содержащее в качестве подграфа граф \(G'\), построенный на \((k-1)\)-м шаге алгоритма. Существует хотя бы одно такое дерево \(T\) (по гипотезе индукции).

Разберем два случая:

  1. \((u_k, v_k)\) принадлежит \(T\).

    В этом случае утверждение на \(k\)-м шаге истинно. Доказывать нечего.

  2. \((u_k, v_k)\) не принадлежит \(T\).

    Напомним, что ребро \((u_k, v_k)\) выбиралось так, что \(d(u_k, v_k) = \min\{d(u, v) \colon (u, v) \in E, \; u \in V', \; V \in V \setminus V'\}\).

    Разобьем дерево \(T\) на три подграфа - два поддерева и соединяющее их ребро:

    \(T_1 = (V_1, E_1), \quad V_1 = V'\) ;

    \(T_2 = (V_2, E_2), \quad V_2 = V \setminus V'\) ;

    \(T_3 = (V_3, E_3), \quad V_3 = \{u, v\}\) .

    Здесь \((u, v) \neq (u_k, v_k)\), поскольку ребро \((u_k, v_k)\) не принадлежит \(T\).

    Заменим ребро \((u, v)\), соединяющее подграфы \(T_1\) и \(T_2\), на ребро \((u_k, v_k)\) - получим новое остовное дерево \(T'\). Докажем его минимальность. В самом деле, в результате замены ребра \((u, v)\) на ребро \((u_k, v_k)\) стоимость остовного дерева не увеличится. Следовательно, стоимость дерева \(T'\) минимальна.

    Значит, в графе \(G\) существует минимальное остовное дерево \(T'\), содержащее подграф \(G'\), построенный на \((k-1)\)-м шаге, и ребро \((u_k, v_k)\). А это и есть подграф \(G'\), построенный на \(k\)-м шаге.

Из доказанного утверждения вытекает, что после выполнения всех шагов алгоритма будет построено минимальное остовное дерево графа \(G\). Корректность алгоритма доказана.