103
Действительно, довольно просто по заданному графу и номеру
вершины a получить список смежных с a вершин. Для этого достаточно
отфильтровать список всех вершин [1..n] функцией, задающей ребра
графа:
listCont :: Graph -> Int -> [Int]
listCont (n, fc) a = [ b | b <- [1..n], fc a b ]
или еще короче:
listCont (n, fc) a = filter (fc a) [1..n]
Теперь функция преобразования графа в представление в виде
списков смежности получается в одну строку:
convert :: Graph -> [(Int, [Int])]
convert g@(n, fc) = map (\a -> (a, listCont a g)) [1..n]
В полученном представлении все вершины имеют номера от 1 до n,
и каждая вершина имеет свой список смежности, возможно, пустой. Для
такого графа решение предыдущей задачи получается даже проще, чем это
было представлено в листинге У2.6.
Мы, однако, не будем менять представление графа и попытаемся
найти решение, использующее заданное представление. Для
этого
построим функцию, которая находит список всех достижимых из заданной
вершины вершин графа. Как и в предыдущей задаче это можно сделать с
помощью поиска в ширину.
Классический алгоритм поиска в ширину состоит из шагов, на
каждом из которых имеется три множества вершин, которые условно
можно назвать «черными», «серыми» и «белыми».
Черные вершины – это
те, которые уже были пройдены во время работы алгоритма. Если в
процессе поиска алгоритм снова находит черную вершину, то она
игнорируется. Серые вершины – это те, которые образуют «фронт волны»,
то есть те, списки смежности которых будут исследованы на очередном
шаге алгоритма. Наконец, белые вершины – это вершины, которые еще
не
попали ни в список черных, ни в список серых вершин; это вершины, еще
не исследованные алгоритмом.
В начале работы множество черных вершин пусто, множество серых
вершин содержит единственную начальную вершину, остальные вершины
– белые. На очередном шаге алгоритма исследуются все вершины,
смежные с серыми. Если исследуемая вершина является серой или
черной,
то она просто пропускается, а если вершина – белая, то она
перекрашивается в серый цвет и будет исследоваться на следующем шаге
работы алгоритма. Все вершины, которые на предыдущем шаге работы
алгоритма были серыми, становятся черными на следующем шаге.
Алгоритм заканчивает работу, когда множество серых вершин
оказывается пустым. В этот момент
множество черных вершин как раз и
будет составлять множество всех достижимых из начальной вершины
вершин графа.