Использование обхода в глубину для проверки связности — различия между версиями
м (rollbackEdits.php mass rollback)  | 
				|||
| (не показаны 22 промежуточные версии 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>.  | |
| − | + | ||
| − |       return   | + | === Реализация ===  | 
| − | + | ||
| + |  <font color=green>// visited {{---}} массив цветов вершин</font>    | ||
| + | |||
| + |  '''int''' dfs(u: '''int''', visited: '''bool[]'''):                | ||
| + |      '''int''' visitedVertices = 1  | ||
| + |      visited[u] = ''true''                           <font color=green>// помечаем вершину как пройденную</font>  | ||
| + |      '''for''' v: uv <tex>\in</tex> E                               <font color=green>// проходим по смежным с u вершинам</font>  | ||
| + |          '''if''' '''not''' visited[v]                       <font color=green>// проверяем, не находились ли мы ранее в выбранной вершине</font>  | ||
| + |              visitedVertices += dfs(v, visited)  | ||
| + |       '''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
Проверка связности вершин в режиме онлайн
| Задача: | 
| Дан пустой граф , состоящий из вершин. Поступают запросы, каждый из которых — это пара вершин, между которыми надо добавить ребро. Необходимо в любой момент времени для двух выбранных вершин отвечать на вопрос, являются ли они связанными. | 
Алгоритм
Описываемая здесь идея довольна проста и будет основываться на системе непересекающихся множеств.
В каждом множестве будем хранить компоненты связности графа . Тогда ответ на запросы второго типа будет заключаться в определении множеств, в которых находятся данные вершины, т.е. две вершины являются связанными, если они лежат в одной компоненте связности. Изначально все вершины находятся в разных компонентах связности. При добавлении ребра объединяем множества, в которых находятся его концы, если те различны.