<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=78.25.120.113&amp;*</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=78.25.120.113&amp;*"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/78.25.120.113"/>
		<updated>2026-04-15T05:04:15Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A5%D1%8C%D1%8E%D0%B8&amp;diff=51732</id>
		<title>Алгоритм Хьюи</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A5%D1%8C%D1%8E%D0%B8&amp;diff=51732"/>
				<updated>2016-01-23T15:01:36Z</updated>
		
		<summary type="html">&lt;p&gt;78.25.120.113: /* Обоснование корректности */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Задача&lt;br /&gt;
|definition=Дано [[Основные определения теории графов#oriented_grath|ориентированное]] [[Дерево, эквивалентные определения#tree|дерево]], вершины которого раскрашены в цвета. Найти &amp;lt;tex&amp;gt;dc:V\rightarrow \{1\ldots k\}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;dc(u) -&amp;lt;/tex&amp;gt; число различных цветов в поддереве с корнем в вершине &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;. Время работы: &amp;lt;tex&amp;gt;O(V)&amp;lt;/tex&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Простое решение==&lt;br /&gt;
Ответ на задачу можно получить достаточно просто с помощью битовых масок. Для начала в каждую вершину поместим битовую маску с цветом данной вершины. Запустим [[Обход в глубину, цвета вершин|обход в глубину]] и на выходе из каждой вершины будем записывать в неё результат побитового &amp;lt;tex&amp;gt;OR&amp;lt;/tex&amp;gt; масок её детей и её самой. Таким образом в каждой вершине будет храниться битовая маска с цветами, лежащими в данном поддереве. Общая сложность алгоритма будет &amp;lt;tex&amp;gt;O(V \cdot K)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;K\ -&amp;lt;/tex&amp;gt; количество цветов. Если количество цветов меньше размера машинного слова, то сложность составит &amp;lt;tex&amp;gt;O(V)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Алгоритм решения==&lt;br /&gt;
Будем в каждой вершине дерева хранить по числу, так, чтобы для каждого поддерева ответом была сумма всех значений в вершинах в данном поддереве. Для начала каждой вершине в качестве значения присвоим &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. Теперь, если бы все вершины имели различные цвета, надо было бы пройти снизу вверх по дереву и просуммировать для каждой вершины числа, записанные в её детях. Но некоторые вершины будут иметь одинаковые цвета, и это надо как-то учитывать. &lt;br /&gt;
&lt;br /&gt;
Для этого запустим обход в глубину. Также будем хранить для каждого цвета последнюю посещенную вершину данного цвета в массиве &amp;lt;tex&amp;gt;last[k]&amp;lt;/tex&amp;gt;. Теперь, заходя в &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ую вершину с цветом &amp;lt;tex&amp;gt;col&amp;lt;/tex&amp;gt;, смотрим: если вершина с таким цветом еще не встречалась, то просто присваиваем &amp;lt;tex&amp;gt;last[col]=i&amp;lt;/tex&amp;gt;, иначе, если вершина с данным цветом уже встречалась, то находим [[Сведение задачи LCA к задаче RMQ|наименьшего общего предка]] данной вершины и последней вершины с таким цветом и вычитаем из их предка &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;, присваиваем &amp;lt;tex&amp;gt;last[col]=i&amp;lt;/tex&amp;gt;. Теперь при выходе из вершины можно просуммировать числа в ее детях и получить ответ для данной вершины, так как для нее все дети уже подсчитаны. &lt;br /&gt;
&lt;br /&gt;
Таким образом, алгоритм запускает один обход в глубину, на каждой итерации которого ищет наименьшего общего предка. Если искать наименьшего общего предка за &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;, к примеру [[Алгоритм Фарака-Колтона и Бендера|алгоритмом Фарака-Колтона и Бендера]], то сложность работы алгоритма будет &amp;lt;tex&amp;gt;O(V)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Пример==&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
! № шага !! Изображение !! Описание&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
| 0&lt;br /&gt;
| [[Файл:algo_0.png|300px]]&lt;br /&gt;
| Расставим у каждой вершины &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
| 1&lt;br /&gt;
| [[Файл:algo_1.png|300px]]&lt;br /&gt;
| Выходим из &amp;lt;tex&amp;gt;8&amp;lt;/tex&amp;gt;-ой вершины. Так как желтых вершин еще не было, запоминаем её как последнюю желтую.&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
| 2&lt;br /&gt;
| [[Файл:algo_2.png|300px]]&lt;br /&gt;
| &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;-ая вершина. Последняя желтая &amp;lt;tex&amp;gt;-\ 8&amp;lt;/tex&amp;gt;-ая. Их LCA &amp;lt;tex&amp;gt;\ -4&amp;lt;/tex&amp;gt;-ая вершина. Вычитаем из значения &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;-ой вершины &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; и запоминаем текущую как последнюю желтую.&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
| 8&lt;br /&gt;
| [[Файл:8.png|300px]]&lt;br /&gt;
| Пропустим несколько тривиальных шагов. Выходим из &amp;lt;tex&amp;gt;11&amp;lt;/tex&amp;gt;-ой вершины. Последней посещенной зеленой была &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt;-ая (не &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;-я). Вычитаем из их LCA (&amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;-ой вершины) &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; и запоминаем &amp;lt;tex&amp;gt;11&amp;lt;/tex&amp;gt;-ую как последнюю зеленую.&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
| 9&lt;br /&gt;
| [[Файл:9.png|300px]]&lt;br /&gt;
| Выходим из &amp;lt;tex&amp;gt;7&amp;lt;/tex&amp;gt;-ой вершины. Последней синей была &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;-ая. Вычтем из их LCA &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; и запомним &amp;lt;tex&amp;gt;7&amp;lt;/tex&amp;gt;-ую как последнюю синюю.&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
| суммирование&lt;br /&gt;
| [[Файл:algo_12.png|300px]]&lt;br /&gt;
|Пропустим еще два шага. В результате суммирования получаем в каждой вершине ответ на задачу для поддерева.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Псевдокод==&lt;br /&gt;
 '''int''' col[MAX_COL], used[MAX_N], sum[MAX_N]&lt;br /&gt;
 &lt;br /&gt;
 '''func''' dfs('''Node''' v)''':'''&lt;br /&gt;
    used[v] = ''true''&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;u \in&amp;lt;/tex&amp;gt; v.children&lt;br /&gt;
        '''if''' !used[u]&lt;br /&gt;
            dfs(u)&lt;br /&gt;
        sum[v] += sum[u]&lt;br /&gt;
    '''if''' last[col[v]] != -1&lt;br /&gt;
         sum[lca(v, last[col[v]])]--&lt;br /&gt;
    last[col[v]] = v&lt;br /&gt;
        &lt;br /&gt;
 '''func''' hugh('''int''' n, '''int''' k, '''Node''' root)''':'''&lt;br /&gt;
    '''for''' &amp;lt;tex&amp;gt;v \in V&amp;lt;/tex&amp;gt;&lt;br /&gt;
        used[v] = ''false''&lt;br /&gt;
        sum[v] = 1&lt;br /&gt;
    '''for''' i = 1 '''to''' k&lt;br /&gt;
        last[i] = -1&lt;br /&gt;
    dfs(root)&lt;br /&gt;
&lt;br /&gt;
==Обоснование корректности==&lt;br /&gt;
Отсортируем вершины по времени входа. Рассмотрим вершину &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;, в поддереве которой &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; вершин одного цвета. Так как мы обходим вершины в порядке времени входа, эти &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; вершин мы обойдем последовательно. Их наименьший общий предок будет лежать в данном поддереве. Следовательно мы вычтем &amp;lt;tex&amp;gt;k-1&amp;lt;/tex&amp;gt; раз единицу из вершины &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;. Для любых других двух вершин их наименьший общий предок не будет лежать в данном поддереве. Следовательно для каждого поддерева учтется по одной вершине каждого цвета, существующего в данном поддереве.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
*[[Алгоритм Тарьяна поиска LCA за O(1) в оффлайн]]&lt;br /&gt;
&lt;br /&gt;
*[[Метод двоичного подъема]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Задача о наименьшем общем предке]]&lt;/div&gt;</summary>
		<author><name>78.25.120.113</name></author>	</entry>

	</feed>