Алгоритмы на деревьях — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
м (переименовал Диаметр дерева в Алгоритмы на деревьях: Расширение темы)
Строка 1: Строка 1:
 
__TOC__
 
__TOC__
'''Диаметр дерева''' - максимальная длина (в рёбрах) кратчайшего пути между любыми двумя вершинами.
 
Алгоритм в этой статье находит диаметр в дереве.
 
  
Пусть дан граф <tex>G = \langle V, E \rangle </tex> Тогда диаметром <tex>d</tex> называется <tex>\max\limits_{u, v \in V} dist(v, u)</tex>, где <tex>dist</tex> — кратчайшее расстояние между вершинами
+
== Диаметр дерева ==
  
== Алгоритм ==
+
'''Диаметр дерева''' — максимальная длина (в рёбрах) кратчайшего пути между любыми двумя вершинами.
 +
 
 +
Пусть дан граф <tex>G = \langle V, E \rangle </tex> Тогда диаметром <tex>d</tex> называется <tex>\max\limits_{u, v \in V} dist(v, u)</tex>, где <tex>dist</tex> — кратчайшее расстояние между вершинами.
 +
 
 +
=== Алгоритм ===
 
Возьмём любую вершину <tex> v \in V </tex> и найдём расстояния до всех других вершин.
 
Возьмём любую вершину <tex> v \in V </tex> и найдём расстояния до всех других вершин.
 
<tex>d[i] = \min\limits_{u, i \in V} dist(u, i)</tex>
 
<tex>d[i] = \min\limits_{u, i \in V} dist(u, i)</tex>
  
 
+
Возьмём вершину <tex> u \in V </tex> такую, что <tex>d[u] \ge d[t]</tex> для любого <tex>t</tex>. Снова найдём расстояние от <tex>u</tex> до всех остальных вершин. Самое большое расстояние диаметр дерева.
Возьмём вершину <tex> u \in V </tex> такую, что <tex>d[u] \ge d[t]</tex> для любого <tex>t</tex>.Снова найдём расстояние от <tex>u</tex> до всех остальных вершин. Самое большое расстояние {{---}} диаметр дерева.
 
 
Расстояние до остальных вершин будем искать алгоритмом <tex>BFS</tex>.
 
Расстояние до остальных вершин будем искать алгоритмом <tex>BFS</tex>.
  
== Реализация ==
+
=== Реализация ===
 
 
  
  int diameterTree(graph g)               
+
  '''int''' diameterTree(graph g)               
{
 
 
     v = u = w = 0;
 
     v = u = w = 0;
 
     d = bfs(g, v);  
 
     d = bfs(g, v);  
     for (i = 0; i < n; i++)
+
     '''for''' i = 0; i < n; i++
           if (d[i] > d[u])
+
           '''if''' d[i] > d[u]
 
               u = i;
 
               u = i;
 
     bfs(g, u);
 
     bfs(g, u);
     for (i = 0; i < n; i++)
+
     '''for''' i = 0; i < n; i++
           if (d[i] > d[w])
+
           '''if''' d[i] > d[w]
 
                 w = i;
 
                 w = i;
     return d[w];
+
     '''return''' d[w];
}
 
 
 
 
 
 
 
 
 
 
== Обоснование корректности ==
 
Будем пользоваться свойством, что в любом дереве больше одного листа. Исключительный случай-дерево из одной вершины,но алгоритм сработает верно и в этом случае.
 
  
 +
=== Обоснование корректности ===
 +
Будем пользоваться свойством, что в любом дереве больше одного листа. Исключительный случай — дерево из одной вершины, но алгоритм сработает верно и в этом случае.
  
 
{{Теорема
 
{{Теорема
 
|statement=
 
|statement=
Искомое расстояние - есть расстояние между двумя листами.
+
Искомое расстояние — это расстояние между двумя листами.
 
|proof=
 
|proof=
Пусть искомое расстояние - есть расстояние между вершинами <tex>a, b</tex> где <tex>b</tex> - не является листом. Т.к. b не является листом, то значит её степень больше еденицы, следовательно из неё существует ребро в непосещенную вершину (дважды посетить вершину <tex>b</tex> мы не можем). Лемма доказана.
+
Пусть искомое расстояние расстояние между вершинами <tex>a, b</tex>, где <tex>b</tex> не является листом. Так как b не является листом, то значит её степень больше единицы, следовательно из неё существует ребро в непосещённую вершину (дважды посетить вершину <tex>b</tex> мы не можем). Лемма доказана.
 
}}
 
}}
 
 
 
  
 
После запуска алгоритма получим дерево <tex>BFS</tex>.
 
После запуска алгоритма получим дерево <tex>BFS</tex>.
Строка 55: Строка 45:
 
|proof=
 
|proof=
 
Предположим существует ребро <tex>u, v</tex> между соседними поддеревьями:
 
Предположим существует ребро <tex>u, v</tex> между соседними поддеревьями:
Рассмотрим первую вершину в которую приведет наш алгоритм, предположим это вершина <tex>u</tex>, тогда в ходе рассмотрения всех смежных вершин <tex>u</tex> мы добавим в список вершину <tex>v</tex>, тем самым исключив возможность попадания их в разные поддеревья.
+
Рассмотрим первую вершину, в которую приведет наш алгоритм, предположим, это вершина <tex>u</tex>, тогда в ходе рассмотрения всех смежных вершин <tex>u</tex> мы добавим в список вершину <tex>v</tex>, тем самым исключив возможность попадания их в разные поддеревья.
 
}}
 
}}
  
  
 
+
Мы свели задачу к нахождению вершины <tex>w</tex>, такой что сумма глубин поддеревьев максимальна.
 
 
 
 
 
 
Мы свели задачу к нахождению вершины <tex>w</tex>, такой, что сумма глубин поддеревьев максимальна.
 
  
 
Докажем, что одно из искомых поддеревьев содержит самый глубокий лист.  
 
Докажем, что одно из искомых поддеревьев содержит самый глубокий лист.  
Пусть нет, тогда взяв расстояние от <tex>w</tex> до глубочайшего листа мы можем улучшить ответ.
+
Пусть нет, тогда, взяв расстояние от <tex>w</tex> до глубочайшего листа, мы можем улучшить ответ.  
 
 
Таким образом мы доказали, что нам нужно взять вершину <tex>u</tex> с наибольшей глубиной после первого <tex>bfs</tex>, очевидно что ей в пару надо сопоставить вершину <tex>w</tex> , что <tex>dist(u, w)</tex> {{---}} максимально. Очевидно, что проблема решается запуском bfs из <tex>u</tex>.  
 
  
 +
Таким образом мы доказали, что нам нужно взять вершину <tex>u</tex> с наибольшей глубиной после первого <tex>bfs</tex>, очевидно что ей в пару надо сопоставить вершину <tex>w</tex>, такую что <tex>dist(u, w)</tex> максимально. Очевидно, что проблема решается запуском bfs из <tex>u</tex>.
  
== Оценка производительности ==
+
=== Оценка производительности ===
Все операции кроме <tex>BFS</tex> {{---}} <tex>O(1)</tex>.
+
Все операции кроме <tex>BFS</tex> <tex>O(1)</tex>.
<tex>BFS</tex> работает линейное время, запускаем мы его 2 раза.Получаем <tex>O(V + E)</tex>.
+
<tex>BFS</tex> работает за линейное время, запускаем мы его 2 раза. Получаем <tex>O(V + E)</tex>.

Версия 22:04, 10 января 2015

Диаметр дерева

Диаметр дерева — максимальная длина (в рёбрах) кратчайшего пути между любыми двумя вершинами.

Пусть дан граф [math]G = \langle V, E \rangle [/math] Тогда диаметром [math]d[/math] называется [math]\max\limits_{u, v \in V} dist(v, u)[/math], где [math]dist[/math] — кратчайшее расстояние между вершинами.

Алгоритм

Возьмём любую вершину [math] v \in V [/math] и найдём расстояния до всех других вершин. [math]d[i] = \min\limits_{u, i \in V} dist(u, i)[/math]

Возьмём вершину [math] u \in V [/math] такую, что [math]d[u] \ge d[t][/math] для любого [math]t[/math]. Снова найдём расстояние от [math]u[/math] до всех остальных вершин. Самое большое расстояние — диаметр дерева. Расстояние до остальных вершин будем искать алгоритмом [math]BFS[/math].

Реализация

int diameterTree(graph g)              
    v = u = w = 0;
    d = bfs(g, v); 
    for i = 0; i < n; i++
         if d[i] > d[u]
              u = i;
    bfs(g, u);
    for i = 0; i < n; i++
          if d[i] > d[w]
               w = i;
    return d[w];

Обоснование корректности

Будем пользоваться свойством, что в любом дереве больше одного листа. Исключительный случай — дерево из одной вершины, но алгоритм сработает верно и в этом случае.

Теорема:
Искомое расстояние — это расстояние между двумя листами.
Доказательство:
[math]\triangleright[/math]
Пусть искомое расстояние — расстояние между вершинами [math]a, b[/math], где [math]b[/math] не является листом. Так как b не является листом, то значит её степень больше единицы, следовательно из неё существует ребро в непосещённую вершину (дважды посетить вершину [math]b[/math] мы не можем). Лемма доказана.
[math]\triangleleft[/math]

После запуска алгоритма получим дерево [math]BFS[/math].

Теорема:
В дереве BFS не существует ребер между вершинами из разных поддеревьев некоторого их общего предка.
Доказательство:
[math]\triangleright[/math]

Предположим существует ребро [math]u, v[/math] между соседними поддеревьями:

Рассмотрим первую вершину, в которую приведет наш алгоритм, предположим, это вершина [math]u[/math], тогда в ходе рассмотрения всех смежных вершин [math]u[/math] мы добавим в список вершину [math]v[/math], тем самым исключив возможность попадания их в разные поддеревья.
[math]\triangleleft[/math]


Мы свели задачу к нахождению вершины [math]w[/math], такой что сумма глубин поддеревьев максимальна.

Докажем, что одно из искомых поддеревьев содержит самый глубокий лист. Пусть нет, тогда, взяв расстояние от [math]w[/math] до глубочайшего листа, мы можем улучшить ответ.

Таким образом мы доказали, что нам нужно взять вершину [math]u[/math] с наибольшей глубиной после первого [math]bfs[/math], очевидно что ей в пару надо сопоставить вершину [math]w[/math], такую что [math]dist(u, w)[/math] максимально. Очевидно, что проблема решается запуском bfs из [math]u[/math].

Оценка производительности

Все операции кроме [math]BFS[/math][math]O(1)[/math]. [math]BFS[/math] работает за линейное время, запускаем мы его 2 раза. Получаем [math]O(V + E)[/math].