Способы представления
ТеорияДо сих пор мы задавали ориентированные и неориентированные графы, изображая их с помощью рисунков. Можно задать граф как пару множеств, следуя определению, однако этот способ довольно громоздкий и представляет, скорее, теоретический интерес. Развитие алгоритмических подходов к анализу свойств графов требует иных способов описания графов, более пригодных для практических вычислений, в том числе с использованием ЭВМ. Рассмотрим три наиболее распространенных способа представления графов.
Предположим, что все вершины и все ребра неориентированного графа или все вершины и все дуги (включая петли) ориентированного графа пронумерованы начиная с единицы. Граф (неориентированный или ориентированный) может быть представлен в виде матрицы типа пхт, где п — число вершин, am — число ребер (или дуг). Для неориентированного графа элементы этой матрицы задаются следующим образом:
Для ориентированного графа элементы матрицы задаются так:
Матрицу (aij) типа n × m, определенную указанным образом, называют матрицей инциденции.
Пример 5.5. Для ориентированного графа, представленного на рис. 5.8, нумерация вершин уже задана. Зададим нумерацию дуг следующим образом: дуге (v1, v2) присвоим номер 1, дуге (v1, v3) — 2, дуге (v2, v3) — 3 и дуге (v3, v2) — 4.
Матрицу инциденции удобно заполнять по столбцам, записывая для k-й дуги (vi, vj) 1 в i-й и —1 в j-й строках k-го столбца и 0 во всех остальный строках k-го столбца. В результате получим матрицу. #
Несмотря на то что представление графа в виде матрицы инциденции играет весьма большую роль в теоретических исследованиях, практически этот способ весьма неэффективен. Прежде всего, в матрице в каждом столбце только два ненулевых элемента, что делает этот способ представления графа неэкономным при большом количестве вершин. Кроме того, решение практических задач с помощью матрицы инциденции весьма трудоемко.
Оценим, например, временные затраты на решение с помощью матрицы инциденции такой простой задачи в ориентированном графе: для данной вершины vk найти ее „окружение" — множество преемников и множество предшественников вершины vk, т.е. множество всех вершин, непосредственно достижимых из vk, и множество всех вершин, из которых она непосредственно достижима.
Для решения этой задачи на матрице инциденций ориентированного графа нужно идти по строке с номером к до появления ненулевого элемента (+1 или —1). В случае если обнаружена +1, в соответствующем столбце надо найти строку, в которой записано число —1. Номер строки, в которой стоит это число, дает номер вершины, непосредственно достижимой из данной вершины. Если обнаружена — 1, в столбце надо найти строку, в которой записана 1, и получить номер вершины, из которой непосредственно достижима данная вершина. Для получения всего „окружения" надо проделать указанный поиск для всех ненулевых элементов k-й строки. Наиболее трудоемкой процедурой является поиск ненулевого элемента в столбце. Число таких процедур поиска равно степени вершины vk. Будем в этом случае говорить, что сложность алгоритма анализа окружения вершины vk составляет O(dgvk) (порядка dgvk).
Можно увидеть, что поиск „ окружения" всех вершин займет время порядка произведения числа вершин ориентированного графа на сумму степеней всех вершин, которая, как можно показать, пропорциональна числу дуг ориентированного графа. Таким образом, сложность алгоритма поиска „ окружения" составляет О(nm), т.е. поиск занимает время порядка произведения числа вершин на число дуг.
Более эффективной матричной структурой, представляющей граф, служит матрица смежности вершин, или булева матрица графа. Это квадратная матрица В порядка n, элементы которой определяют следующим образом:
для неориентированного графа
для ориентированного графа
Заметим, что в k-й строке матрицы ориентированного графа количество единиц равно полустепени исхода dg+vk вершины vk, а количество единиц в k-м столбце — полустепени захода dg-vk.Для неориентированного графа матрица смежности вершин симметрическая.
Для ориентированного графа, изображенного на рис. 5.8, матрица смежности вершин имеет вид
Рассмотрим решение задачи поиска „окружения" с использованием матрицы смежности вершин. Для определения „окружения" вершины vk нужно сначала идти по k-й строке матрицы и искать ненулевые элементы. Если элемент aki = 1, то вершина vi достижима из вершины vk. После просмотра k-й строки надо просмотреть k-й столбец. Если элемент ajk = 1, то вершина vk достижима из вершины vj.
Можно показать, что с использованием матрицы смежности вершин решение задачи поиска „ окружения" всех вершин ориентированного графа будет иметь сложность порядка n2, что эффективнее предыдущей оценки nm, если число дуг ориентированного графа превышает число его вершин, а это часто бывает в практических задачах.
Матрица смежности верпган является достаточно эффективным способом представления графов. Однако эту матрицу удобно строить по графу, уже заданному каким-либо способом, например рисунком. Во многих задачах граф создается динамически, т.е. в ходе решения задачи меняется множество вершин и множество ребер (или дуг). В этом случае эффективным способом машинного представления графа являются списки смежности (или списки инцидентности).
Рассмотрим ориентированный граф. Для задания множества вершин, непосредственно достижимых из вершины v, используют линейный однонаправленный список*. Каждый элемент такого списка включает данные (например, некоторое число) и указатель на следующий элемент списка. Список в целом задается указателем на его первый элемент (голову списка). Последний элемент списка содержит „пустой" указатель (рис. 5.11).
Задать для вершины v ее список смежности означает в произвольном порядке поместить в данные элементов списка номера вершин u, для которых в ориентированном графе есть дуга из v в u (v → u). Список смежности вершины v обозначают L(v).
Отметим, что список смежности вершины может при необходимости дополняться. Для этого в последнем элементе списка ппустой" указатель заменяется указателем на добавляемый элемент, который становится последним элементом списка с „пустым" указателем.
Если количество вершин ориентированного графа известно заранее, то ориентированный граф удобно задавать в виде структуры, называемой массивом лидеров.
Под массивом мы понимаем матрицу-столбец, элементами которой могут быть некоторые объекты (например, элементы списка смежности). Их называют элементами массива. Число элементов массива лидеров равно числу вершин графа. Элементами массива лидеров являются первые элементы списков смежности вершин ориентированного графа. Пример представления ориентированного графа списками смежности, собранными в массив лидеров, представлен на рис. 5.12.
* Подробное описание обработки списков и всей „программистской" терминологии, использованной в этом абзаце, см.: Вирт Н.
С использованием списков смежности совсем просто решается задача поиска преемников данной вершины: для этого достаточно просмотреть список смежности вершины, затратив на это время, пропорциональное ее полустепени исхода. Тогда на решение этой задачи для всего ориентированного графа потребуется время порядка числа его дуг.
Менее эффективно решается задача поиска предшественников вершины, так как в этом случае необходимо, вообще говоря, просмотреть списки смежности всех вершин с целью поиска в них данной вершины.
Таким образом, задача поиска я окружения" с использованием списков смежности является более трудоемкой, чем в случае использования матриц. Однако удобство динамического формирования описания ориентированного графа в данном случае перевешивает. Бели задача поиска предшественников возникает часто, можно использовать двусторонние списки смежности, сопоставляя каждой вершине уже два списка — преемников и предшественников.
Описанные способы представления графа списками не исчерпывают всех возможных вариантов, и в литературе по программированию можно найти разнообразные варианты ганизации списков. Поскольку эти особенности относятся к технологии программирования, мы не будем в них углубляться и в дальнейшем для простоты при описании различных алгоритмов будем считать, что (односторонние) списки смежности собраны в массив лидеров, так как в рассматриваемых ниже алгоритмах анализа графов именно анализ множества преемников вершины наиболее важен.
Неориентированный граф задать с помощью списков смежности можно так же, как и ориентированный. Здесь в список смежности вершины v войдут все вершины, смежные с ней, а списки смежности могут быть собраны в массив лидеров. Для неориентированого графа задача поиска „ окружения" одной вершины требует однократного просмотра ее списка смежности, и затраты времени на это пропорциональны степени вершины. На решение задачи поиска „окружения" для всего неориентированного графа потребуется время, пропорциональ- пропорциональное произведению числа вершин графа на число его ребер.
В заключение рассмотрим еще одну матрицу, характеризующую граф, — так называемую матрицу достижимости. Это квадратная матрица С порядка |V|, каждый элемент cij которой равен 1, если j-я вершина достижима из i-й вершины, и равен 0 если иначе. Отметим, что, согласно определению достижимости, элементы cij = 1.
Метод вычисления матрицы достижимости ориентированного графа по его матрице смежности будет рассмотрен в 5.6. Матрица достижимости несет очень важную информацию об ориентированном графе. Ее анализ позволяет, например, найти его бикомпоненты и компоненты.
По определению, в бикомпоненту входят взаимно достижимые вершины. Для двух таких вершин с номерами i и j должно выполняться равенство cij = cij = 1. Поэтому, чтобы найти бикомпоненту, в которую входит i-я вершина ориентированного графа, нужно просмотреть i-ю строку и i-й столбец матрицы достижимости С и сформировать множество Pi = {р: cip = cpi = 1} номеров вершин, порождающих искомую бикомпоненту. Из определения матрицы достижимости вытекает, что в Pi содержатся номера всех вершин данной поненты. Поскольку две различные бикомпоненты не пересекаются, вершины с номерами из множества Pi при поиске других бикомпонент из рассмотрения можно исключить. Процесс поиска целесообразно начать с первой вершины. Он закончится, когда для каждой вершины будет найдена содержащая ее компонента. При этом может оказаться, что некоторые (а может быть, и все) бикомпоненты содержат только по одной вершине, поскольку каждая вершина, по определению, достижима сама из себя.
Поиск компонент ориентированного графа сложнее, так как в компоненту входят вершины с номерами i и j, для которых cij — 1 или cji = 1. Кроме того, одна и та же вершина может входить в несколько различных компонент. Отметим, что любая бикомпонента или не пересекается с некоторой компонентой, или целиком в нее входит.
Мы не будем приводить общий алгоритм поиска компонент, а рассмотрим его на примере.
Пример 5.6. Для ориентированного графа, изображенного на рис. 5.9, имеем матрицу достижимости
Начнем с поиска бикомпонент. Для первой вершины множество P1 = {1} включает только ее саму. Для второй вершины имеем Р2 = {2,3}, для четвертой — Р4 = {4,5} и для шестой — P6 = {6,7}. Соответственно полученные множества вершин порождают бикомпоненты В1, B2, B3 и В4 изображенные на рис. 5.9.
Перейдем к поиску компонент. Используя матрицу С, выпишем для каждой вершины vi, i = 1,7, множество Кi, состоящее из тех вершин, которые достижимы из i-й вершины или из которых достижима она.
В рассматриваемом ориентированном графе для вершины v1 в множество К1 входят вершины, для которых c1j = 1 или cj1 = = 1, т.е. К1 = {v1, v2, v3, v4, v5}. Для вершин v2, и v3, множества K2 и К3 совпадают с множеством К1. Поскольку все элементы четвертого и пятого столбцов матрицы С равны единице, то для вершин v4 и v5 имеем К4 = К5 = {v1, v2, v3, v4, v5, v6, v7}.
Для вершин v6 и v7 получим K6 = K7 = {v4, v5, v6, v7}.
Кроме того, если некоторая компонента Сз содержит вершины vi и vj, то вершина vm будет принадлежать этой компоненте в том и только в том случае, если vm ∈ Ki ∩ Kj.
Действительно, пусть вершина vm принадлежит компоненте Сp вместе с вершинами vi и vj. Тогда либо вершина vm достижима из вершины vi, либо, наоборот, vi достижима из vm, и, следовательно, vm G К^ Из аналогичных рассуждений выте- вытекает, что vm ∈ Ki. Таким образом, вершина vm принадлежит пересечению множеств Ki и Kj.
Пусть теперь вершины vi и vj принадлежат компоненте Сp и vm ∈ Ki ∩ Kj. Тогда вершина vm также принадлежит компоненте Сp, поскольку либо вершина vi достижима из vm, либо vm достижима из vi, и для вершин vj и vm ситуация аналогична.
Начнем строить компоненты, содержащие вершину v1. Рассмотрим множество К1. Так как вершина v2 принадлежит множеству K1, найдется по крайней мере одна компонента, в которую входят обе эти вершины. Обозначим ее через С1. Вершина v3 будет принадлежать этой компоненте в том и только в том случае, если v3 ∈ K1 ∩ K2 Непосредственная проверка показывает, что последнее условие выполняется.
Можно заметить, что
K1 ∩ K2 ∩ K3 ∩ K4 ∩ K5 = K1
поэтому компонента С1 (см. рис. 5.9) есть подграф, порожденный множеством К1, и вершина v1 не может входить в какую-либо другую компоненту, отличную от С1. Поскольку в компоненту С1 вошли все вершины из множеств К2 и К3, то вершины v2 и v3 также не входят ни в какие другие компоненты.
Перейдем к поиску компонент, отличных от C1, в которые входит вершина v4. В множестве К4 содержится вершина v5. Пересечению множеств К4 и К5 принадлежат вершины v6 и v7, не вошедшие в выделенную компоненту С1. Рассуждая аналогично и учитывая, что v4 и v5 принадлежат бикомпоненте В3, a v6 и v7 — бикомпоненте В4 получаем, что компонента С2 порождается множеством вершин и других компонент в рассматриваемом ориентированном графе нет.