Использование обхода в глубину для проверки связности — различия между версиями
(→Реализация) |
м (rollbackEdits.php mass rollback) |
||
(не показаны 23 промежуточные версии 6 участников) | |||
Строка 1: | Строка 1: | ||
− | == | + | == Алгоритм проверки наличия пути между двумя вершинами == |
− | |||
− | + | {{Задача | |
+ | |definition = | ||
+ | Дан граф <tex>G = (V, E)</tex> и две вершины <tex>s</tex> и <tex>t</tex>. Необходимо проверить, существует ли путь из вершины <tex>s</tex> в вершину <tex>t</tex> по рёбрам графа <tex>G</tex>. | ||
+ | }} | ||
+ | === Алгоритм === | ||
− | + | Небольшая модификация алгоритма [[Обход в глубину, цвета вершин|обхода в глубину]]. Смысл алгоритма заключается в том, чтобы запустить обход в глубину из вершины <tex>s</tex> и проверять при каждом посещении вершины, не является ли она искомой вершиной <tex>t</tex>. | |
− | Небольшая модификация алгоритма [[Обход в глубину, цвета вершин|обхода в глубину]]. Смысл алгоритма заключается в том, чтобы запустить обход в глубину из вершины | + | Так как в первый момент времени все пути в графе "белые", то если вершина <tex>t</tex> и была достижима из <tex>s</tex>, то по [[Лемма о белых путях|лемме о белых путях]] в какой-то момент времени мы зайдём в вершину <tex>t</tex>, чтобы её покрасить. Время работы алгоритма <tex>O(|V| + |E|)</tex>. |
− | Так как в первый момент времени все пути в графе "белые", то если вершина | ||
=== Реализация === | === Реализация === | ||
− | + | ||
+ | <font color=green>// visited {{---}} массив цветов вершин</font> | ||
+ | <font color=green>// t {{---}} конечная вершина</font> | ||
− | bool dfs(int | + | '''bool''' dfs(u, t: '''int''', visited: '''bool[]'''): |
− | + | '''if''' u == t | |
− | if | + | '''return''' ''true'' |
− | return true | + | visited[u] = ''true'' <font color=green>// помечаем вершину как пройденную</font> |
− | visited[u] = true | + | '''for''' v: uv <tex>\in</tex> E <font color=green>// проходим по смежным с u вершинам</font> |
− | for | + | '''if''' '''not''' visited[v] <font color=green>// проверяем, не находились ли мы ранее в выбранной вершине</font> |
− | if | + | '''if''' dfs(v, t, visited) |
− | if | + | '''return''' ''true'' |
− | return true | + | '''return''' ''false'' |
− | return false | + | |
− | + | == Алгоритм проверки связности графа G == | |
− | + | ||
− | + | {{Задача | |
− | + | |definition = | |
− | + | Дан [[Основные определения теории графов|неориентированный граф]] <tex>G = (V, E)</tex>. Необходимо проверить, является ли он связным. | |
− | + | }} | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | == Алгоритм | + | === Алгоритм === |
− | + | Снова небольшая модификация алгоритма [[Обход в глубину, цвета вершин|обхода в глубину]], в которой будем возвращать количество посещенных вершин. Запустим такой <code>dfs()</code> от некоторой вершины графа <tex>G</tex>, если его результат равен <tex>|V|</tex>, то мы побывали во всех вершинах графа, а следовательно он связен, иначе какие-то вершины остались непосещенными. Работает алгоритм за <tex>O(|V| + |E|)</tex>. | |
=== Реализация === | === Реализация === | ||
− | + | ||
− | + | <font color=green>// visited {{---}} массив цветов вершин</font> | |
− | + | ||
− | + | '''int''' dfs(u: '''int''', visited: '''bool[]'''): | |
− | + | '''int''' visitedVertices = 1 | |
− | + | visited[u] = ''true'' <font color=green>// помечаем вершину как пройденную</font> | |
− | visited[u] = true | + | '''for''' v: uv <tex>\in</tex> E <font color=green>// проходим по смежным с u вершинам</font> |
− | for | + | '''if''' '''not''' visited[v] <font color=green>// проверяем, не находились ли мы ранее в выбранной вершине</font> |
− | if | + | visitedVertices += dfs(v, visited) |
− | dfs(v) | + | '''return''' visitedVertices |
− | + | ||
− | + | ==Проверка связности вершин в режиме онлайн== | |
− | + | {{Задача | |
− | + | |definition = | |
− | + | Дан пустой граф <tex>G</tex>, состоящий из <tex>n</tex> вершин. Поступают запросы, каждый из которых {{---}} это пара вершин, между которыми надо добавить ребро. Необходимо в любой момент времени для двух выбранных вершин отвечать на вопрос, являются ли они связанными. | |
− | + | }} | |
− | + | ===Алгоритм=== | |
− | + | Описываемая здесь идея довольна проста и будет основываться на [[СНМ (наивные реализации)|системе непересекающихся множеств]]. | |
− | + | ||
− | + | В каждом множестве будем хранить компоненты связности графа <tex>G</tex>. Тогда ответ на запросы второго типа будет заключаться в определении множеств, в которых находятся данные вершины, т.е. две вершины являются связанными, если они лежат в одной компоненте связности. Изначально все вершины находятся в разных компонентах связности. При добавлении ребра объединяем множества, в которых находятся его концы, если те различны. | |
− | + | ||
− | + | == См. также == | |
− | + | *[[Обход в глубину, цвета вершин]] | |
− | + | *[[Использование обхода в глубину для поиска цикла]] | |
− | |||
[[Категория: Алгоритмы и структуры данных]] | [[Категория: Алгоритмы и структуры данных]] | ||
[[Категория: Обход в глубину]] | [[Категория: Обход в глубину]] |
Текущая версия на 19:17, 4 сентября 2022
Содержание
Алгоритм проверки наличия пути между двумя вершинами
Задача: |
Дан граф | и две вершины и . Необходимо проверить, существует ли путь из вершины в вершину по рёбрам графа .
Алгоритм
Небольшая модификация алгоритма обхода в глубину. Смысл алгоритма заключается в том, чтобы запустить обход в глубину из вершины и проверять при каждом посещении вершины, не является ли она искомой вершиной . Так как в первый момент времени все пути в графе "белые", то если вершина и была достижима из , то по лемме о белых путях в какой-то момент времени мы зайдём в вершину , чтобы её покрасить. Время работы алгоритма .
Реализация
// visited — массив цветов вершин
// t — конечная вершина
bool dfs(u, t: int, visited: bool[]):
if u == t
return true
visited[u] = true // помечаем вершину как пройденную
for v: uv
E // проходим по смежным с u вершинам
if not visited[v] // проверяем, не находились ли мы ранее в выбранной вершине
if dfs(v, t, visited)
return true
return false
Алгоритм проверки связности графа G
Задача: |
Дан неориентированный граф . Необходимо проверить, является ли он связным. |
Алгоритм
Снова небольшая модификация алгоритма обхода в глубину, в которой будем возвращать количество посещенных вершин. Запустим такой dfs()
от некоторой вершины графа , если его результат равен , то мы побывали во всех вершинах графа, а следовательно он связен, иначе какие-то вершины остались непосещенными. Работает алгоритм за .
Реализация
// visited — массив цветов вершин
int dfs(u: int, visited: bool[]):
int visitedVertices = 1
visited[u] = true // помечаем вершину как пройденную
for v: uv
E // проходим по смежным с u вершинам
if not visited[v] // проверяем, не находились ли мы ранее в выбранной вершине
visitedVertices += dfs(v, visited)
return visitedVertices
Проверка связности вершин в режиме онлайн
Задача: |
Дан пустой граф | , состоящий из вершин. Поступают запросы, каждый из которых — это пара вершин, между которыми надо добавить ребро. Необходимо в любой момент времени для двух выбранных вершин отвечать на вопрос, являются ли они связанными.
Алгоритм
Описываемая здесь идея довольна проста и будет основываться на системе непересекающихся множеств.
В каждом множестве будем хранить компоненты связности графа
. Тогда ответ на запросы второго типа будет заключаться в определении множеств, в которых находятся данные вершины, т.е. две вершины являются связанными, если они лежат в одной компоненте связности. Изначально все вершины находятся в разных компонентах связности. При добавлении ребра объединяем множества, в которых находятся его концы, если те различны.