<?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=188.162.65.20&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=188.162.65.20&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/188.162.65.20"/>
		<updated>2026-05-19T18:04:08Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=1outtreesumwc&amp;diff=54719</id>
		<title>1outtreesumwc</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=1outtreesumwc&amp;diff=54719"/>
				<updated>2016-06-06T14:23:37Z</updated>
		
		<summary type="html">&lt;p&gt;188.162.65.20: /* Источники информации */ исправлена первая категория&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tex dpi = &amp;quot;200&amp;quot; &amp;gt;1 \mid outtree \mid \sum w_i C_i&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Задача&lt;br /&gt;
|definition=&lt;br /&gt;
Необходимо составить расписание на одном станке работ с произвольными временами выполнения. Минимизировать нужно взвешенную сумму времен завершения работ. Зависимости между работами заданы исходящим [[Дерево, эквивалентные определения | деревом]] {{---}} работа, которая соответствует корню, доступна в начале, все другие работы зависят от одной работы {{---}} отца в дереве. &lt;br /&gt;
}}&lt;br /&gt;
Тривиальным примером подобной задачи является демонтаж сложного механизма.&lt;br /&gt;
&lt;br /&gt;
== Свойства оптимального расписания ==&lt;br /&gt;
&lt;br /&gt;
Докажем некоторые свойства оптимального расписания, которые мы будем использовать в доказательстве корректности алгоритма.&lt;br /&gt;
&lt;br /&gt;
Введем некоторые обозначения для удобства. За &amp;lt;tex&amp;gt;\mathrm{edges} &amp;lt;/tex&amp;gt; обозначим список всех ребёр дерева. Для всех работ &amp;lt;tex&amp;gt;i = 1, \ldots, n&amp;lt;/tex&amp;gt; обозначим за &amp;lt;tex&amp;gt;S(i)&amp;lt;/tex&amp;gt; всех потомков &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; в дереве зависимостей, включая саму работу &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, введём новый параметр работы &amp;lt;tex&amp;gt;q_i = \dfrac{w_i}{p_i}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Для подмножества работ &amp;lt;tex&amp;gt;I \subseteq \{1, \ldots, n\}&amp;lt;/tex&amp;gt; определим:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;w(I) = \sum\limits_{i \in I} w_i, p(I) = \sum\limits_{i \in I} p_i, q(I) = \dfrac{w(I)}{p(I)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Два непересекающихся множества работ &amp;lt;tex&amp;gt;I, J \subseteq \{1, \ldots, n\}&amp;lt;/tex&amp;gt; будем называть '''параллельными''' &amp;lt;tex&amp;gt;(I \sim J)&amp;lt;/tex&amp;gt;, если для всех &amp;lt;tex&amp;gt;i \in I, j \in J&amp;lt;/tex&amp;gt; выполняется: &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; не является ни предком, ни потомком &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;. Если множества состоят из одной работы &amp;lt;tex&amp;gt;I = \{i\},\ J = \{j\}&amp;lt;/tex&amp;gt;, будем писать &amp;lt;tex&amp;gt;i \sim j&amp;lt;/tex&amp;gt;. Каждое расписание представлено перестановкой &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1&lt;br /&gt;
|statement= Пусть &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt; {{---}} оптимальное расписание, &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt; {{---}} два таких параллельных блока (множества работ, выполняемых последовательно) из &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt; выполняется сразу после &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;\pi'&amp;lt;/tex&amp;gt; {{---}} расписание, полученное из &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt; перестановкой &amp;lt;tex&amp;gt;I&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;J&amp;lt;/tex&amp;gt;. Тогда выполяются следующие пункты:&lt;br /&gt;
:&amp;lt;tex&amp;gt;(a)~ I \sim J \Rightarrow q(I) \geqslant q(J)&amp;lt;/tex&amp;gt; &lt;br /&gt;
:&amp;lt;tex&amp;gt;(b)&amp;lt;/tex&amp;gt; Если &amp;lt;tex&amp;gt;I \sim J&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;q(I) = q(J)&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\pi'&amp;lt;/tex&amp;gt; {{---}} оптимальное расписание.&lt;br /&gt;
|proof= &lt;br /&gt;
&amp;lt;tex&amp;gt;(a)&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
:Пусть &amp;lt;tex&amp;gt;f = \sum w_i C_i&amp;lt;/tex&amp;gt;. Так как &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt; {{---}} оптимальное расписание, то &amp;lt;tex&amp;gt;f(\pi) \leqslant f(\pi')&amp;lt;/tex&amp;gt;. Таким образом:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;tex&amp;gt;0 \leqslant f(\pi') - f(\pi) = w(I) p(J) - w(J) p(I)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Поделим на &amp;lt;tex&amp;gt;p(I)p(J)&amp;lt;/tex&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;tex&amp;gt;q(I) = \dfrac{w(I)}{p(I)} \geqslant \dfrac{w(J)}{p(J)} = q(J) &amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;(b)&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
:Если &amp;lt;tex&amp;gt;q(I) = q(J) &amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;f(\pi) = f(\pi') &amp;lt;/tex&amp;gt;, следовательно расписание &amp;lt;tex&amp;gt;\pi'&amp;lt;/tex&amp;gt; оптимально.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|id = theorem1&lt;br /&gt;
|statement = Пусть &amp;lt;tex&amp;gt;i, ~j&amp;lt;/tex&amp;gt; работы такие, что &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; {{---}} предок &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, и &amp;lt;tex&amp;gt; q_j = \max \{q_k \mid ~ (i, k) \in \mathrm{edges} \}&amp;lt;/tex&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
Тогда существует оптимальное расписание, в котором работа &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt; идёт сразу после работы &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof = &lt;br /&gt;
Каждое расписание может быть представлено последовательностью работ в порядке, в котором они выполняются. Пусть &amp;lt;tex&amp;gt; \pi &amp;lt;/tex&amp;gt; будет оптимальной такой последовательностью. Также предположим, что количество работ между &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; равное &amp;lt;tex&amp;gt; l &amp;lt;/tex&amp;gt; было бы минимальным. Можно считать, что &amp;lt;tex&amp;gt; l &amp;gt; 0 &amp;lt;/tex&amp;gt;. Тогда расписание можно представить следующим образом:&lt;br /&gt;
&lt;br /&gt;
[[Файл:JobBlock.jpg]]&lt;br /&gt;
&lt;br /&gt;
Рассмотрим &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; случая.&lt;br /&gt;
&lt;br /&gt;
'''Случай 1''': &amp;lt;tex&amp;gt; k \in S(i) &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Работа &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; не является потомком работы &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; , иначе у неё было бы &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; предка. Следовательно, &amp;lt;tex&amp;gt; k \sim j &amp;lt;/tex&amp;gt;. По [[#lemma1 | лемме]] &amp;lt;tex&amp;gt; q(k) \geqslant q(j) &amp;lt;/tex&amp;gt;, а по условию выбора &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; имеем &amp;lt;tex&amp;gt; q(j) \geqslant q(k) &amp;lt;/tex&amp;gt;, значит, &amp;lt;tex&amp;gt; q(j) = q(k) &amp;lt;/tex&amp;gt;. Опять же из [[#lemma1 | леммы]] следует, что работы &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; можно поменять местами, не ухудшив расписание. Это противоречит тому, что мы выбрали минимальное &amp;lt;tex&amp;gt; l &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Случай 2''': &amp;lt;tex&amp;gt; k \not\in S(i) &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Пусть &amp;lt;tex&amp;gt; h &amp;lt;/tex&amp;gt; будет последней работой в расписании между &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; j\ ( &amp;lt;/tex&amp;gt;включая работу &amp;lt;tex&amp;gt; i) &amp;lt;/tex&amp;gt;, которая принадлежит &amp;lt;tex&amp;gt; S(i) &amp;lt;/tex&amp;gt;, то есть для всех работ &amp;lt;tex&amp;gt; r &amp;lt;/tex&amp;gt; в множестве &amp;lt;tex&amp;gt; K &amp;lt;/tex&amp;gt;, назначенных между &amp;lt;tex&amp;gt; h &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt;, имеем, что &amp;lt;tex&amp;gt; r \not\in S(i) &amp;lt;/tex&amp;gt;. Так как наш [[Основные определения теории графов | граф]] зависимостей работ является исходящим деревом и  &amp;lt;tex&amp;gt;(i, j) \in \mathrm{edges} &amp;lt;/tex&amp;gt;, то любой предок работы &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; также является и предком работы &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;. Поэтому никакая работа из &amp;lt;tex&amp;gt; K &amp;lt;/tex&amp;gt; не является предком &amp;lt;tex&amp;gt; j\ (&amp;lt;/tex&amp;gt;иначе бы она не смогла стоять после &amp;lt;tex&amp;gt; i) &amp;lt;/tex&amp;gt; или потомком, значит, &amp;lt;tex&amp;gt; K \sim j &amp;lt;/tex&amp;gt;. Из этого следует, что &amp;lt;tex&amp;gt; q(K) \geqslant q(j) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:Работа &amp;lt;tex&amp;gt; h \in S(i) &amp;lt;/tex&amp;gt; не является потомком какой-либо работы &amp;lt;tex&amp;gt; r \in K &amp;lt;/tex&amp;gt;. В противном же случае получалось, что &amp;lt;tex&amp;gt; r \in S(i) &amp;lt;/tex&amp;gt;, значит, &amp;lt;tex&amp;gt; h &amp;lt;/tex&amp;gt; является не последней работой из &amp;lt;tex&amp;gt; S(i) &amp;lt;/tex&amp;gt; между &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt;. Поэтому &amp;lt;tex&amp;gt; h \sim K &amp;lt;/tex&amp;gt;, откуда тут же следует, что &amp;lt;tex&amp;gt; q(h) \geqslant q(K) \geqslant q(j) &amp;lt;/tex&amp;gt;. По определению &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; имеем, что &amp;lt;tex&amp;gt; q(j) \geqslant q(h) &amp;lt;/tex&amp;gt;, следовательно &amp;lt;tex&amp;gt; q(j) = q(h) = q(K) &amp;lt;/tex&amp;gt;. По [[#lemma1 | лемме]] мы можем поменять блоки &amp;lt;tex&amp;gt; K &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; не нарушив оптимальности расписания.&lt;br /&gt;
&lt;br /&gt;
Таким образом мы можем менять соседние работы или блоки работ, пока &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; не окажется сразу за &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Доказанная в предыдущем пункте [[#theorem1 | теорема]] уже даёт основную идею алгоритма: взять работу &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt;, отличную от корня дерева, с максимальным значением &amp;lt;tex&amp;gt; q_j &amp;lt;/tex&amp;gt;  и поставить её в расписании сразу после своего непосредственного предка &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;. Так как существует оптимальное расписание, в котором работа &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; идёт сразу после &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;, то мы можем объедить вершины графа в одну вершину &amp;lt;tex&amp;gt; J_i  = \{i, j\}&amp;lt;/tex&amp;gt;, которая представляет собой последовательность &amp;lt;tex&amp;gt; \pi_i \colon i, j &amp;lt;/tex&amp;gt;. Все сыновья работы &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; станут сыновьями новой вершины &amp;lt;tex&amp;gt; J_i &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будем повторять процесс слияния вершин, пока не останется всего одна вершина.&lt;br /&gt;
&lt;br /&gt;
Таким образом каждая вершина &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; представляется множеством работ &amp;lt;tex&amp;gt; J_i &amp;lt;/tex&amp;gt; и соответствующей этому множеству последовательностью &amp;lt;tex&amp;gt; \pi_i &amp;lt;/tex&amp;gt;. На очередном шаге алгоритма мы находим вершину &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt;, отличную от корня, с максимальным значением &amp;lt;tex&amp;gt; q_j &amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt; par &amp;lt;/tex&amp;gt; {{---}} непосредственный предок работы &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt;. Тогда нам надо найти такую вершину &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt; par \in J_i &amp;lt;/tex&amp;gt;. После этого мы объединяем обе вершины, заменяя &amp;lt;tex&amp;gt; J_i &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; \pi_i &amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt; J_i \cup J_j &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; \pi_i \circ \pi_j &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; \pi_i \circ \pi_j &amp;lt;/tex&amp;gt; {{---}} это конкатенация последовательностей &amp;lt;tex&amp;gt; \pi_i &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; \pi_j &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Детали описаны в алгоритме ниже, в котором&lt;br /&gt;
* &amp;lt;tex&amp;gt; E(i) &amp;lt;/tex&amp;gt; обозначает последнюю работу в последовательности &amp;lt;tex&amp;gt; \pi_i &amp;lt;/tex&amp;gt;,&lt;br /&gt;
* &amp;lt;tex&amp;gt; P(i) &amp;lt;/tex&amp;gt; обозначает предка в графе зависимостей, а после слияния с какой-то вершиной &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; {{---}} предыдущую работу в последовательности &amp;lt;tex&amp;gt; \pi_j &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
  w[root] = &amp;lt;tex&amp;gt; - \infty &amp;lt;/tex&amp;gt;&lt;br /&gt;
  '''for''' i = 1..n&lt;br /&gt;
    E[i] = {i} &lt;br /&gt;
    J[i] = {i} &lt;br /&gt;
    q[i] = w[i] \ p[i]&lt;br /&gt;
  L = {1, ... , n}&lt;br /&gt;
  '''while''' L &amp;lt;tex&amp;gt; \ne &amp;lt;/tex&amp;gt; {root} &amp;lt;font color=darkgreen&amp;gt;// пока в списке работ не останется только корень&amp;lt;/font&amp;gt;&lt;br /&gt;
    Найти работу j &amp;lt;tex&amp;gt; \in &amp;lt;/tex&amp;gt; L с маскимальным значением q[j]&lt;br /&gt;
    par = P[j]&lt;br /&gt;
    Найти i, что par &amp;lt;tex&amp;gt; \in &amp;lt;/tex&amp;gt; J[i]&lt;br /&gt;
    w[i] += w[j]&lt;br /&gt;
    p[i] += p[j]&lt;br /&gt;
    q[i] = w[i] / w[j]    &amp;lt;font color=darkgreen&amp;gt;// пересчитаем значения в вершине&amp;lt;/font&amp;gt;&lt;br /&gt;
    P[j] = E[i]           &amp;lt;font color=darkgreen&amp;gt;// предком работы j теперь будет последняя работа в &amp;lt;tex&amp;gt; \pi_i &amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    E[i] = E[j]           &amp;lt;font color=darkgreen&amp;gt;// последней работой в &amp;lt;tex&amp;gt; \pi_i &amp;lt;/tex&amp;gt; теперь будет последняя работа в &amp;lt;tex&amp;gt; \pi_j &amp;lt;/tex&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
    J[i] = J[i] &amp;lt;tex&amp;gt; \cup &amp;lt;/tex&amp;gt; J[j]&lt;br /&gt;
    L = L \ {j}&lt;br /&gt;
Вначале делаем присваивание &amp;lt;tex&amp;gt; w(root) = -\infty &amp;lt;/tex&amp;gt;, чтобы корень никогда не выбрался на шаге выбора вершины с максимальным значением &amp;lt;tex&amp;gt; q &amp;lt;/tex&amp;gt;. В реализации же можно просто дополнительно проверять на равенство с корнем, чтобы избежать переполнений или испортить значение &amp;lt;tex&amp;gt;-\infty&amp;lt;/tex&amp;gt;.  &lt;br /&gt;
&lt;br /&gt;
После завершения этой процедуры оптимальное расписание можно восстановить с конца, зная &amp;lt;tex&amp;gt; E(root) &amp;lt;/tex&amp;gt; и массив &amp;lt;tex&amp;gt; P &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Если для получения работы &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; с минимальным значением &amp;lt;tex&amp;gt; q(j) &amp;lt;/tex&amp;gt; использовать очередь с приоритетами, а для поиска родителям вершины использовать систему непересекающихся множеств, то время работы алгоритма будет &amp;lt;tex&amp;gt; \mathcal{O}(n\log{n}) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Проиллюстрируем работу алгоритма на следующем примере.&lt;br /&gt;
&lt;br /&gt;
[[Файл:JobsOuttrees.jpg|650px]]&lt;br /&gt;
&lt;br /&gt;
Первой выберется работа с номером &amp;lt;tex&amp;gt; 5 &amp;lt;/tex&amp;gt;. Она объединиться со своим родителем &amp;lt;tex&amp;gt; 2 &amp;lt;/tex&amp;gt; и допишется в конец &amp;lt;tex&amp;gt; \pi_2 &amp;lt;/tex&amp;gt;. Потом выберется работа &amp;lt;tex&amp;gt; 4 &amp;lt;/tex&amp;gt;, потом &amp;lt;tex&amp;gt; \{2, 5\} &amp;lt;/tex&amp;gt; и т. д. Процесс будет продолжаться, пока не останется одна вершина. Ответ {{---}} оптимальная последовательность работ {{---}} содержится в &amp;lt;tex&amp;gt; \pi_1 &amp;lt;/tex&amp;gt;, который написан внутри последней вершины.&lt;br /&gt;
&lt;br /&gt;
== Доказательство оптимальности алгоритма ==&lt;br /&gt;
{{Теорема&lt;br /&gt;
|id = theorem2&lt;br /&gt;
|statement = Алгоритм &amp;lt;tex&amp;gt; 1 \mid outtree \mid \sum w_i C_i&amp;lt;/tex&amp;gt; строит оптимальное расписание.&lt;br /&gt;
|proof = &lt;br /&gt;
Доказательство проведём по индукции. Очевидно, что для одной вершины алгоритм построит оптимальное расписание. Пусть теперь он может составить оптимальную последовательность назначенных работ числом меньше &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt;. Пусть также работы &amp;lt;tex&amp;gt; i, j &amp;lt;/tex&amp;gt; {{---}} работы, которые объединятся на первом шаге алгоритма. Тогда оптимальное расписание &amp;lt;tex&amp;gt; R &amp;lt;/tex&amp;gt; можно представить следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \pi \colon \pi (1), \ldots, \pi (k), i, j, \pi (k + 3), \ldots, \pi (n) &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После объединения работ &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; в одну расписание &amp;lt;tex&amp;gt; R' &amp;lt;/tex&amp;gt; примет такой вид:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; \pi ' \colon \pi (1), \ldots, \pi (k), I, \pi (k + 3), \ldots, \pi (n) &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;tex&amp;gt; I = \{i, j\}, ~w(I) = w(i) + w(j), p(I) = p(i) + p(j)&amp;lt;/tex&amp;gt;. Обозначим за &amp;lt;tex&amp;gt; f_n(\pi ), ~f_{n-1}(\pi ') &amp;lt;/tex&amp;gt; целевые функции для последовательностей &amp;lt;tex&amp;gt; \pi &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; \pi ' &amp;lt;/tex&amp;gt; соответственно. Тогда &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; f_n(\pi ) - f_{n-1}(\pi') = w(i)p(i) + w(j)(p(i) + p(j)) - (w(i) + w(j))(p(i) + p(j)) = -w(i) p(j)\ (*) &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Следовательно, расписание &amp;lt;tex&amp;gt; R &amp;lt;/tex&amp;gt; будет оптимальным тогда и только тогда, когда расписание &amp;lt;tex&amp;gt; R' &amp;lt;/tex&amp;gt; будет оптимальным. А по предположению индукции наш алгоритм составит оптимальное расписание для последовательности &amp;lt;tex&amp;gt; \pi ' &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь разделим обе части равенства &amp;lt;tex&amp;gt; (*) &amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt; w(i)w(j) &amp;lt;/tex&amp;gt;. Получим, что расстояние между целевыми функциями равно&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt; -\dfrac{p(j)}{w(j)} = -\dfrac{1}{q(j)} &amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Это расстояние минимально (по модулю), так как мы выбирали работу &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; с максимальным значением &amp;lt;tex&amp;gt; q(j) &amp;lt;/tex&amp;gt;. Из этих утверждений и следует оптимальность построенного алгоритмом расписания. &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Применение алгоритма в задаче с intree-зависимостью ==&lt;br /&gt;
Сведем задачу &amp;lt;tex&amp;gt; S_{in} = 1 \mid intree \mid \sum w_i C_i &amp;lt;/tex&amp;gt; к решенной задаче &amp;lt;tex&amp;gt;S_{out} = 1 \mid outtree \mid \sum w_i C_i &amp;lt;/tex&amp;gt; следующим образом:&lt;br /&gt;
* Развернем все ребра, теперь если работа &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; зависела от работы &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt;, работа &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; будет зависеть от &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;.&lt;br /&gt;
* Заменим все стоимости &amp;lt;tex&amp;gt; w_i &amp;lt;/tex&amp;gt; на противоположные &amp;lt;tex&amp;gt; w'_i = - w_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=Развернутое оптимальное расписание соответствующей задачи &amp;lt;tex&amp;gt; S_{out} &amp;lt;/tex&amp;gt; с весами &amp;lt;tex&amp;gt; w'_i &amp;lt;/tex&amp;gt; является оптимальным расписанием для задачи  &amp;lt;tex&amp;gt; S_{in} &amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Полученное расписание будет допустимым, так как расписание для &amp;lt;tex&amp;gt; S_{out} &amp;lt;/tex&amp;gt; было допустимым, и в нем никакие две работы не пересекались и не прерывались. Развернув, мы не могли нарушить это свойство. Также из-за того, что мы развернули расписание, мы добились того, что все работы выполняются в правильном порядке (в расписании для &amp;lt;tex&amp;gt; S_{out} &amp;lt;/tex&amp;gt; из-за того, что все ребра были развернуты, порядок был нарушен для всех работ). Таким образом, получили что расписание — допустимое.&lt;br /&gt;
&lt;br /&gt;
Пусть с помощью задачи &amp;lt;tex&amp;gt; S_{out} &amp;lt;/tex&amp;gt; мы получили последовательность работ &amp;lt;tex&amp;gt; 1 \dots n &amp;lt;/tex&amp;gt;. Распишем по определению значение целевой функции для &amp;lt;tex&amp;gt; S_{out} &amp;lt;/tex&amp;gt;:&lt;br /&gt;
&amp;lt;tex&amp;gt;\sum -w_i C_i = \sum \limits_{i=1}^n ( -w_i \sum \limits_{j=1}^i p_j ) = \\&lt;br /&gt;
\sum\limits_{i=1}^n ( w_i \sum\limits_{j=i+1}^n p_j ) - \sum\limits_{i=1}^n w_i \sum \limits_{i=1}^n p_i = \\&lt;br /&gt;
\sum\limits_{i=1}^n ( w_i \sum\limits_{j=i}^n p_j ) - \sum\limits_{i=1}^n w_i p_i - \sum\limits_{i=1}^n w_i \sum \limits_{i=1}^n p_i &amp;lt;/tex&amp;gt;&lt;br /&gt;
Заметим, что первое слагаемое соответствует целевой функции &amp;lt;tex&amp;gt; \sum w_i C_i &amp;lt;/tex&amp;gt; для последовательности &amp;lt;tex&amp;gt; n \dots 1 &amp;lt;/tex&amp;gt;, а второе и третье слагаемые — константы, зависящие только от входных данных и не зависящие от перестановки работ. Таким образом, оптимальное значение для &amp;lt;tex&amp;gt; S_{out} &amp;lt;/tex&amp;gt; также минимизирует &amp;lt;tex&amp;gt; S_{in} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* P. Brucker. Scheduling Algorithms (2006), 5th edition, стр. 73 - 78&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Теория расписаний]]&lt;/div&gt;</summary>
		<author><name>188.162.65.20</name></author>	</entry>

	</feed>