1

Тема: Ещё задача на дереве

Дано неориентированное дерево (2*10^5 вершин) и число k. Мы можем заразить вершину и вместе с ней автоматически заразятся все вершины, удалённые от неё не более чем на k ребер. Нужно за минимальное число заражений заразить всё дерево.
Я пытался делать что-то типа динамики по поддеревьям: хранится информация, насколько удалёна последняя заражённая вершина от корня рассматриваемого поддерева и сколько в поддереве заражённых вершин. На основе этого мы обновляем эти значения для текущей вершины.
Но чувствую,что это лажа), проходит тестов 10.
Задача D отсюда http://neerc.ifmo.ru/school/io/archive/ … vidual.pdf
Бредокод здесь http://ideone.com/FuPnO

2

Re: Ещё задача на дереве

Вроде жадно можно. Просто пускаем обход по дереву, как бы идём от листьев вверх, и как только оказывается, что мы в текущей вершине обязаны заражать, то заражаем. Т.е. делаем dfs, который возвращает расстояние до самого далёкого незаражённого потомка, и если в текущей вершине это значение получилось равно k - заражаем её, иначе - нет.

3

Re: Ещё задача на дереве

Да, я вроде так и делал. Но когда мы заразили текущую вершину, то от неё заражение пойдёт наверх во все достижимые вершины и в них тоже нужно быстро обновлять значения, как это корректно обойти?

4

Re: Ещё задача на дереве

Когда заражаешь какую-то клетку, возвращаешь -k. Т.е. возвращаемое значение может быть отрицательным, и надо написать обход так, чтобы с отрицательными числами всё было адекватно тоже.

5 Отредактировано Jumbo (2012-01-07 16:56:02)

Re: Ещё задача на дереве

Переписал код, теперь работает так: есть массив int h[], если h[v]==-1, то в поддереве всё заражено, иначе это расстояние то самой далёкой незаражённой и есть функция помечающая все заражённые вершины от источника.
И в зависимости от того помечена ли вершина и какое расстояние запучкаем заражение или нет.
Это теперь проходит большинство тестов, но на некоторых всё равно падает.
В общем вот http://ideone.com/2jOOo
Можете глянуть, если не сложно? Там немного.

6

Re: Ещё задача на дереве

Нет, насколько я помню, вполне там можно обойтись без пометок.

Кажется, что незачем передавать в dfs значение, пришедшее "сверху": ведь в таком решении то, что происходит выше текущей вершины, - не особенно-то и важно. Это решение заражает вершины в жадном порядке, каждый раз заражая только действительно необходимую вершину. Поэтому передавать ничего не надо, а просто надо посмотреть: если мы после запуска dfs из всех потомков видим, что один какой-то потомок вернул отрицательное число, превосходящее по модулю все положительные числа из других потомков - то все эти положительные потомки можно мысленно "удалить".

UPD:

Переписал код, теперь работает так: есть массив int h[], если h[v]==-1

Надо не -1, а -k, потому что это важно, на каком именно расстоянии произошло ближайшее снизу заражение.

7 Отредактировано Jumbo (2012-01-07 23:22:42)

Re: Ещё задача на дереве

Надо не -1, а -k, потому что это важно, на каком именно расстоянии произошло ближайшее снизу заражение.

Теперь при нахождении нужной вершины я сразу заражаю (помечаю) всех возможных от неё же.
Захожу в 1-го предка допустим -> заразил его (пометил все на расстоянии k ребёр) -> иду в следующего и смотрю какая сама глубокая непомеченая.
h[v] = -1 это теперь метка что в этом поддереве все нормально.

Но так уж и быть, попробую без пометок теперь)

UPD: написал правильное решение наконец)
Кстати, если мы заражаем вершину, то расстояние до ближайшей незаражённой - это -k-1, а не -k yikes
UPD2: забыл поблагодарить.
Спасибо огромное за помощь!