← Все вопросы

Project selection / задача о выборе проектов — как свести максимизацию прибыли к минимальному разрезу?

Задан 8 месяцев назад1.2к просмотров2 ответа
9

Классическая задача: есть проекты с прибылью (или убытком) и зависимости «чтобы взять проект A, надо взять проект B». Нужно выбрать подмножество проектов с максимальной суммарной прибылью при соблюдении зависимостей. Слышал, что это решается через минимальный разрез / max-flow. Как построить сеть?

2 ответа

15
✓ Принятый ответ — помог автору

Это каноническая задача project selection (она же maximum weight closure). Сводится к минимальному разрезу.

Построение сети. Исток ss, сток tt. Для каждого проекта ii с прибылью pip_i:

  • если pi>0p_i > 0 — ребро sis \to i пропускной pip_i;
  • если pi<0p_i < 0 — ребро iti \to t пропускной pi|p_i|;
  • зависимость «ii требует jj» — ребро iji \to j пропускной \infty.

Пусть P=pi>0piP = \sum_{p_i>0} p_i — сумма всех положительных прибылей. Тогда:

максимальная прибыль=Pmincut(s,t).\text{максимальная прибыль} = P - \text{mincut}(s,t).

Почему работает. Бесконечные рёбра зависимостей делают невозможным «разрезать» зависимость — значит в части SS (со стороны истока, выбранные проекты) лежат только замкнутые относительно зависимостей множества. Минимальный разрез отрезает либо «упущенную прибыль» (не взяли плюсовой проект — режем ребро sis\to i), либо «обязательный убыток» (взяли минусовой — режем iti\to t). Минимизируя сумму отрезанного, максимизируем чистую прибыль.

long long P = 0;
for(int i=0;i<n;i++){
    if(p[i] > 0){ P += p[i]; add_edge(s, i, p[i]); }
    else if(p[i] < 0) add_edge(i, t, -p[i]);
}
for(auto&[i,j]:deps) add_edge(i, j, INF); // i требует j
long long answer = P - maxflow(s, t);

Восстановление выбранных проектов: после maxflow — это вершины, достижимые из ss в остаточной сети (множество SS минимального разреза).

Грабли: INF для рёбер зависимостей берите достаточно большим (больше суммы всех |p|), но не LLONG_MAX — иначе при сложении в потоке переполнение. Все веса — long long.

6

Это частный случай более общей задачи maximum weight closure на ориентированном графе: выбрать замкнутое (по исходящим рёбрам) подмножество вершин с максимальной суммой весов. Стандартный приём — ровно тот, что описан: плюсовые веса вешаем на ss, минусовые на tt, рёбра графа делаем бесконечными, считаем PmincutP - \text{mincut}. Распознать такую задачу на олимпиаде помогает формулировка вида «если берём X, обязаны взять Y» вместе с прибылями/штрафами — почти всегда это min-cut. Если зависимости двусторонние или есть взаимоисключения, конструкция усложняется, но ядро то же.

Ваш ответ

Войдите, чтобы ответить на вопрос.