Динамика по поддеревьям — различия между версиями
| Mihver1 (обсуждение | вклад) м (→Решение) | Mihver1 (обсуждение | вклад)   (→Динамика по деревьям) | ||
| Строка 1: | Строка 1: | ||
| =Динамика по деревьям= | =Динамика по деревьям= | ||
| − | Рассмотрим динамику по дереву на примере задачи о максимальном  | + | Рассмотрим динамику по дереву на примере задачи о максимальном взвешенном паросочетании в дереве. | 
| ==Задача о максимальном взвешенном паросочетании на дереве== | ==Задача о максимальном взвешенном паросочетании на дереве== | ||
| ===Формулировка=== | ===Формулировка=== | ||
| Строка 8: | Строка 8: | ||
| ===Решение=== | ===Решение=== | ||
| [[Файл:parosochetanie.png|100px|right|frame|Максимальное взвешенное паросочетание]] | [[Файл:parosochetanie.png|100px|right|frame|Максимальное взвешенное паросочетание]] | ||
| − | |||
| Главное отличие этой задачи от других динамически решаемых {{---}} ответ в одном поддереве влияет на решение в остальных. | Главное отличие этой задачи от других динамически решаемых {{---}} ответ в одном поддереве влияет на решение в остальных. | ||
| Рассмотрим наше первое состояние, когда еще не выбрана ни одна вершина. В этом случае мы можем сделать две вещи: | Рассмотрим наше первое состояние, когда еще не выбрана ни одна вершина. В этом случае мы можем сделать две вещи: | ||
| − | *  | + | * Занять корень каким-то ребром | 
| − | * Не  | + | * Не занимать корень ребрами | 
| − | В первом случае мы не сможем рассматривать его детей вовсе  | + | В первом случае мы не сможем рассматривать его детей вовсе. В ином случае мы переходим в его поддеревья и выполняем то же самое действие. | 
| + | Если мы оставляем корень свободным, значит может разрешить всем его детям иметь в своих поддеревьях занятый корень. В ином случае мы можем разрешить не всем детям, а только тем, которые уже не заняты ребром из корня. | ||
| ===Рекуррентная формула=== | ===Рекуррентная формула=== | ||
| Строка 26: | Строка 26: | ||
| Теперь наши формулы имеют вид:<br> | Теперь наши формулы имеют вид:<br> | ||
| <tex>dp(u, 0) = \sum_{\text{child}\ v\  of\  u}dp(w, 1)</tex><br> | <tex>dp(u, 0) = \sum_{\text{child}\ v\  of\  u}dp(w, 1)</tex><br> | ||
| − | <tex>dp(u, 1) = \max\left\{dp(u, 0),\ \max_{\text{child}\ x\ of\ u}\{dp(x, 0)\ +\ dp(u, 0) - dp(x, 1)\ +\  | + | <tex>dp(u, 1) = \max\left\{dp(u, 0),\ \max_{\text{child}\ x\ of\ u}\{dp(x, 0)\ +\ dp(u, 0) - dp(x, 1)\ +\ w[u,x]  \}\right\}</tex> | 
| Заметим, что с помощью этого преобразования мы сократили общее время вычисления с <tex>O(n^2)</tex> до <tex>O(n)</tex>. | Заметим, что с помощью этого преобразования мы сократили общее время вычисления с <tex>O(n^2)</tex> до <tex>O(n)</tex>. | ||
| Строка 36: | Строка 36: | ||
|              #вернули уже посчитанное значение dp[v][root] |              #вернули уже посчитанное значение dp[v][root] | ||
|          sum1 = 0 |          sum1 = 0 | ||
| − |          #случай 1: не берем  | + |          #случай 1: не берем ребра из корня | 
| − |          for u in child(v): | + |          if root==0: | 
| − | + |             for u in child(v): | |
| − | + |                 sum1 += calculate(u, 1) | |
| − |          #случай 2: берем  | + |             #выполняем мемоизацию | 
| − |          for  | + |             dp[v][root] = sum1 | 
| − | + |             return sum1 | |
| − | + |          max1 = dp[v][0] | |
| + |          #случай 2: берем какое-то ребро | ||
| + |          for x in child(v): | ||
| + |              max1 = max(max1, calculate(x, 0) + calculate(v, 0) - calculate(x, 1) + w[v,x]) | ||
|          # выполняем мемоизацию |          # выполняем мемоизацию | ||
| − |          dp[v] =  | + |          dp[v][root] = max1 | 
| − |          return dp[v] | + |          return dp[v][root] | 
| − | |||
| − | |||
| ==Общие принципы динамики по поддеревьям== | ==Общие принципы динамики по поддеревьям== | ||
| Самое главное и основное отличие {{---}} ответ в одном поддереве может влиять на другие ответы, как в предыдущей задаче влиял выбор корня. | Самое главное и основное отличие {{---}} ответ в одном поддереве может влиять на другие ответы, как в предыдущей задаче влиял выбор корня. | ||
Версия 21:18, 13 января 2013
Содержание
Динамика по деревьям
Рассмотрим динамику по дереву на примере задачи о максимальном взвешенном паросочетании в дереве.
Задача о максимальном взвешенном паросочетании на дереве
Формулировка
Пусть дано подвешенное за корень дерево, имеющее веса на каждом из ее ребер. Необходимо выбрать такое множество ребер, что бы сумма значений была максимальной и при этом выбранные ребра не являлись бы соседними. Т.е. необходимо решить задачу о максимальном взвешенном паросочетании.
Решение
Главное отличие этой задачи от других динамически решаемых — ответ в одном поддереве влияет на решение в остальных.
Рассмотрим наше первое состояние, когда еще не выбрана ни одна вершина. В этом случае мы можем сделать две вещи:
- Занять корень каким-то ребром
- Не занимать корень ребрами
В первом случае мы не сможем рассматривать его детей вовсе. В ином случае мы переходим в его поддеревья и выполняем то же самое действие. Если мы оставляем корень свободным, значит может разрешить всем его детям иметь в своих поддеревьях занятый корень. В ином случае мы можем разрешить не всем детям, а только тем, которые уже не заняты ребром из корня.
Рекуррентная формула
Заметим, что вторую формулу можно упростить:
Теперь наши формулы имеют вид:
Заметим, что с помощью этого преобразования мы сократили общее время вычисления с до .
Псевдокод
   function calculate(v, root):
       if dp[v][root] != -1:
           return dp[v][root]
           #вернули уже посчитанное значение dp[v][root]
       sum1 = 0
       #случай 1: не берем ребра из корня
       if root==0:
           for u in child(v):
               sum1 += calculate(u, 1)
           #выполняем мемоизацию
           dp[v][root] = sum1
           return sum1
       max1 = dp[v][0]
       #случай 2: берем какое-то ребро
       for x in child(v):
           max1 = max(max1, calculate(x, 0) + calculate(v, 0) - calculate(x, 1) + w[v,x])
       # выполняем мемоизацию
       dp[v][root] = max1
       return dp[v][root]
Общие принципы динамики по поддеревьям
Самое главное и основное отличие — ответ в одном поддереве может влиять на другие ответы, как в предыдущей задаче влиял выбор корня.

