14 added
14 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>В этом уроке разберем, что такое взвешенный граф и для чего он полезен. Также познакомимся с алгоритмом Крускала, и рассмотрим, как и почему он работает.</p>
1
<p>В этом уроке разберем, что такое взвешенный граф и для чего он полезен. Также познакомимся с алгоритмом Крускала, и рассмотрим, как и почему он работает.</p>
2
<h2>Что такое взвешенный граф</h2>
2
<h2>Что такое взвешенный граф</h2>
3
<p><strong>Взвешенный граф</strong>- это граф, в котором каждое ребро обозначается числом. Это число - его вес:</p>
3
<p><strong>Взвешенный граф</strong>- это граф, в котором каждое ребро обозначается числом. Это число - его вес:</p>
4
<p><strong>Вес</strong>- это стоимость использования данного ребра. Например, приведенный выше граф может представлять дорожную сеть, где вершины - это города, ребра - дороги между ними, а вес - стоимость строительства этих дорог.</p>
4
<p><strong>Вес</strong>- это стоимость использования данного ребра. Например, приведенный выше граф может представлять дорожную сеть, где вершины - это города, ребра - дороги между ними, а вес - стоимость строительства этих дорог.</p>
5
<p>Предположим, что мы хотим построить дороги, чтобы добраться из одного города в другой. Нам нужно сделать это как можно дешевле. Так может выглядеть ответ:</p>
5
<p>Предположим, что мы хотим построить дороги, чтобы добраться из одного города в другой. Нам нужно сделать это как можно дешевле. Так может выглядеть ответ:</p>
6
<p>В этом случае нам не нужны циклы, так как мы пытаемся сделать все как можно дешевле. Мы хотим добираться до любой вершины графа, поэтому нам нужно минимальное охватывающее дерево, в котором сумма весов всех ребер в дереве как можно меньше.</p>
6
<p>В этом случае нам не нужны циклы, так как мы пытаемся сделать все как можно дешевле. Мы хотим добираться до любой вершины графа, поэтому нам нужно минимальное охватывающее дерево, в котором сумма весов всех ребер в дереве как можно меньше.</p>
7
-
<p>Существует несколько алгоритмов, чтобы найти минимальные прямые деревья. В этом уроке мы рассмотрим алгоритм Крускала.</p>
7
+
<p>Существует несколько алгоритмов, чтобы найти минимальные остовные деревья. В этом уроке мы рассмотрим алгоритм Крускала.</p>
8
<h2>Что такое алгоритм Крускала</h2>
8
<h2>Что такое алгоритм Крускала</h2>
9
-
<p><strong>Алгоритм Крускала</strong>строит охватывающее дерево графа $G$ по одному ребру за раз. На каждом шаге алгоритма мы берем ребро $G$ с таким весом, чтобы добавление этого ребра в строящееся дерево не создавало цикла.</p>
9
+
<p><strong>Алгоритм Крускала</strong>строит охватывающее дерево графа G по одному ребру за раз. На каждом шаге алгоритма мы берем ребро G с таким весом, чтобы добавление этого ребра в строящееся дерево не создавало цикла.</p>
10
-
<p>Мы можем разрывать связи между весом ребер как угодно, или добавлять ребра до тех пор, пока это не станет невозможным. В графе с $n$ вершинами нам всегда потребуется добавить ровно $n - 1$ ребро.</p>
10
+
<p>Мы можем разрывать связи между весом ребер как угодно, или добавлять ребра до тех пор, пока это не станет невозможным. В графе с n вершинами нам всегда потребуется добавить ровно n - 1 ребро.</p>
11
<p>Так это выглядит (грани выделены в порядке их добавления):</p>
11
<p>Так это выглядит (грани выделены в порядке их добавления):</p>
12
<p>С помощью алгоритма Крускала на каждом шаге выбирается самое дешевое доступное ребро. В этом случае не нужно задумываться о будущих последствиях этого выбора. Эта стратегия всегда дает минимальное остовное дерево.</p>
12
<p>С помощью алгоритма Крускала на каждом шаге выбирается самое дешевое доступное ребро. В этом случае не нужно задумываться о будущих последствиях этого выбора. Эта стратегия всегда дает минимальное остовное дерево.</p>
13
<h2>Почему алгоритм Крускала работает</h2>
13
<h2>Почему алгоритм Крускала работает</h2>
14
-
<p>Разберем несколько причин, почему граф $T$, который строит алгоритм Крускала, действительно остовное дерево графа:</p>
14
+
<p>Разберем несколько причин, почему граф T, который строит алгоритм Крускала, действительно остовное дерево графа:</p>
15
-
<ol><li>У $T$ нет циклов, поскольку алгоритм Крускала не может их создать</li>
15
+
<ol><li>У T нет циклов, поскольку алгоритм Крускала не может их создать</li>
16
-
<li>$T$ - связной граф, иначе мы могли бы добавить ребро между компонентами $T$ без цикла</li>
16
+
<li>T - связной граф, иначе мы могли бы добавить ребро между компонентами T без цикла</li>
17
-
<li>$T$ - охватывающий граф, который включает каждую вершину. Иначе мы могли бы добавить ребро из $T$ в вершину, которая не входит в $T$, не вызывая цикла</li>
17
+
<li>T - охватывающий граф, который включает каждую вершину. Иначе мы могли бы добавить ребро из T в вершину, которая не входит в T, не вызывая цикла</li>
18
-
<li>Мы знаем, что у деревьев на $n$ вершинах всегда $n-1$ ребро, поэтому нам нужно добавить ровно $n - 1$ ребро</li>
18
+
<li>Мы знаем, что у деревьев на n вершинах всегда n-1 ребро, поэтому нам нужно добавить ровно n - 1 ребро</li>
19
-
</ol><p>Теперь рассмотрим, почему у дерева Крускала $T$ - минимальный вес. Представим минимальное расходящееся дерево $S$, которое не равно $T$. Когда мы проходим через процесс Крускала и добавляем ребра, мы добавляем в $T$ ребро $e$, которое не является частью $S$.</p>
19
+
</ol><p>Теперь рассмотрим, почему у дерева Крускала T - минимальный вес. Представим минимальное расходящееся дерево S, которое не равно T. Когда мы проходим через процесс Крускала и добавляем ребра, мы добавляем в T ребро e, которое не является частью S.</p>
20
-
<p>Предположим, мы попытаемся добавить $e$ в $S$. Это создаст цикл по основным свойствам деревьев. Вдоль этого цикла должно быть еще какое-то ребро $d$, которого нет в $T$. $T$ - это дерево, и оно не может содержать все ребра этого цикла.</p>
20
+
<p>Предположим, мы попытаемся добавить e в S. Это создаст цикл по основным свойствам деревьев. Вдоль этого цикла должно быть еще какое-то ребро d, которого нет в T. T - это дерево, и оно не может содержать все ребра этого цикла.</p>
21
-
<p>В этом примере показана гипотетическая часть $S$ вместе с $d$ и $e$:</p>
21
+
<p>В этом примере показана гипотетическая часть S вместе с d и e:</p>
22
-
<p>Теперь удалим $d$ из $S$ и заменим его на $e$ - это дерево $S - d + e$. Если просто менять одно ребро цикла на другое, $S - d + e$ все равно прямое дерево $G$.</p>
22
+
<p>Теперь удалим d из S и заменим его на e - это дерево S - d + e. Если просто менять одно ребро цикла на другое, S - d + e все равно прямое дерево G.</p>
23
-
<p>Процесс Крускала добавил ребро $e$, а не $d$. Это означает, что вес $e$ меньше или равен весу $d$. Это делает $S - d + e$ минимальным прямым деревом $G$, которое согласуется с $T$ на одно ребро больше, чем $S$.</p>
23
+
<p>Процесс Крускала добавил ребро e, а не d. Это означает, что вес e меньше или равен весу d. Это делает S - d + e минимальным прямым деревом G, которое согласуется с T на одно ребро больше, чем S.</p>
24
-
<p>Мы можем повторять этот процесс, пока не получим минимальное остовное дерево, которое согласуется с $T$ по каждому ребру. Это означает, что $T$ должно быть минимальным остовным деревом.</p>
24
+
<p>Мы можем повторять этот процесс, пока не получим минимальное остовное дерево, которое согласуется с T по каждому ребру. Это означает, что T должно быть минимальным остовным деревом.</p>
25
<h2>Выводы</h2>
25
<h2>Выводы</h2>
26
<p>Мы разобрались, что такое взвешенный граф и для чего он полезен. Также познакомились с алгоритмом Крускала, и поняли, почему он работает. Написать код, который реализует алгоритм Крускала, несложно. Самое сложное - проверить, не создает ли добавление ребра цикл. Например, это можно сделать с помощью структуры данных disjoint set.</p>
26
<p>Мы разобрались, что такое взвешенный граф и для чего он полезен. Также познакомились с алгоритмом Крускала, и поняли, почему он работает. Написать код, который реализует алгоритм Крускала, несложно. Самое сложное - проверить, не создает ли добавление ребра цикл. Например, это можно сделать с помощью структуры данных disjoint set.</p>