Проблема минимальной стоимости потока

9

Сетевой поток представляет собой ориентированный граф G = (V, E)с исходной вершиной s ϵ Vи вершиной раковины t ϵ V, и где каждое ребро (u, v) ϵ Eна графике (узлы подключения u ϵ Vи v ϵ V) имеют 2 величин , связанные с этим:

  1. c(u, v) >= 0, емкость края
  2. a(u, v) >= 0, стоимость отправки одной единицы через край

Мы определяем функцию 0 <= f(u, v) <= c(u, v)как число единиц, проходящих через заданное ребро (u, v). Таким образом, стоимость данного ребра (u, v)составляет a(u, v) * f(u, v). Задача потока с минимальными затратами определяется как минимизация общей стоимости по всем ребрам для заданного объема потока d, заданного следующим количеством:

Стоимость

Следующие ограничения относятся к проблеме:

  1. Требования к емкости : поток через заданное ребро не может превышать пропускную способность этого ребра ( f(u, v) <= c(u, v)).
  2. Косая симметрия : поток через заданное ребро должен быть антисимметричным при изменении направления (f(u, v) = -f(v, u) ).
  3. Сохранение потока : чистый поток в любой узел без источника не должен быть равен 0 (для каждого u ∉ {s, t}суммирования по всем w,sum f(u, w) = 0 ).
  4. Требуемый поток : чистый поток из источника и чистый поток в приемник должны равняться требуемому потоку через сеть (суммирование по всем u, sum f(s, u) = sum f(u, t) = d).

Учитывая сеть потока Gи требуемый поток d, выведите минимальную стоимость отправки dединиц через сеть. Вы можете предположить, что решение существует. dи все мощности и затраты будут неотрицательными целыми числами. Для сети с Nвершинами, помеченными как [0, N-1], исходная вершина будет0 а вершина стока будет N-1.

Это поэтому самый короткий ответ (в байтах) выигрывает. Помните, что это соревнование как внутри языков, так и между языками, поэтому не бойтесь публиковать решения на многословном языке.

Встроенные модули разрешены, но рекомендуется включать решения без встроенных функций либо в качестве дополнительного решения в том же ответе, либо в качестве независимого ответа.

Вклад может быть любым разумным образом, который включает в себя мощности и затраты каждого края и спроса.

Тестовые случаи

Контрольные примеры предоставляются в следующем формате:

c=<2D matrix of capacities> a=<2D matrix of costs> d=<demand> -> <solution>

c=[[0, 3, 2, 3, 2], [3, 0, 5, 3, 3], [2, 5, 0, 4, 5], [3, 3, 4, 0, 4], [2, 3, 5, 4, 0]] a=[[0, 1, 1, 2, 1], [1, 0, 1, 2, 3], [1, 1, 0, 2, 2], [2, 2, 2, 0, 3], [1, 3, 2, 3, 0]] d=7 -> 20
c=[[0, 1, 1, 5, 4], [1, 0, 2, 4, 2], [1, 2, 0, 1, 1], [5, 4, 1, 0, 3], [4, 2, 1, 3, 0]] a=[[0, 1, 1, 2, 2], [1, 0, 2, 4, 1], [1, 2, 0, 1, 1], [2, 4, 1, 0, 3], [2, 1, 1, 3, 0]] d=7 -> 17
c=[[0, 1, 4, 5, 4, 2, 3], [1, 0, 5, 4, 3, 3, 5], [4, 5, 0, 1, 5, 5, 5], [5, 4, 1, 0, 3, 2, 5], [4, 3, 5, 3, 0, 4, 4], [2, 3, 5, 2, 4, 0, 2], [3, 5, 5, 5, 4, 2, 0]] a=[[0, 1, 4, 2, 4, 1, 1], [1, 0, 3, 2, 2, 1, 1], [4, 3, 0, 1, 4, 5, 2], [2, 2, 1, 0, 2, 2, 3], [4, 2, 4, 2, 0, 4, 1], [1, 1, 5, 2, 4, 0, 2], [1, 1, 2, 3, 1, 2, 0]] d=10 -> 31
c=[[0, 16, 14, 10, 14, 11, 10, 4, 3, 16], [16, 0, 18, 19, 1, 6, 10, 19, 5, 4], [14, 18, 0, 2, 15, 9, 3, 14, 20, 13], [10, 19, 2, 0, 2, 10, 12, 17, 19, 22], [14, 1, 15, 2, 0, 11, 23, 25, 10, 19], [11, 6, 9, 10, 11, 0, 14, 16, 25, 4], [10, 10, 3, 12, 23, 14, 0, 11, 7, 8], [4, 19, 14, 17, 25, 16, 11, 0, 14, 5], [3, 5, 20, 19, 10, 25, 7, 14, 0, 22], [16, 4, 13, 22, 19, 4, 8, 5, 22, 0]] a=[[0, 12, 4, 2, 9, 1, 1, 3, 1, 6], [12, 0, 12, 16, 1, 2, 9, 13, 2, 3], [4, 12, 0, 2, 2, 2, 2, 10, 1, 1], [2, 16, 2, 0, 2, 1, 8, 4, 4, 2], [9, 1, 2, 2, 0, 5, 6, 23, 5, 8], [1, 2, 2, 1, 5, 0, 13, 12, 12, 1], [1, 9, 2, 8, 6, 13, 0, 9, 4, 4], [3, 13, 10, 4, 23, 12, 9, 0, 13, 1], [1, 2, 1, 4, 5, 12, 4, 13, 0, 13], [6, 3, 1, 2, 8, 1, 4, 1, 13, 0]] d=50 -> 213

Эти тестовые случаи были вычислены с помощью библиотеки Python NetworkX .

Mego
источник
1
Долгое время
Quintec

Ответы:

3

[R + lpSolve ], 201 186 149 144 байта

function(c,a,d,`^`=rep,N=ncol(c),G=diag(N),P=t(1^N),M=P%x%G+G%x%-P)lpSolve::lp(,a,rbind(M,diag(N*N)),c('=','<')^c(N,N*N),c(d,0^(N-2),-d,c))$objv

Попробуйте онлайн!

Код создает следующую линейную задачу и решает ее с помощью lpSolveпакета:

мяNΣИксВ ΣYВAИкс,YеИкс,YsUбJесT Tо:ΣИксВеv,Икс-еИкс,vзнак равно0vВ:v{s,T}ΣИксВеs,Икс-еИкс,sзнак равноdΣИксВеT,Икс-еИкс,Tзнак равно-dеИкс,бСИкс,бИксВ,YВ
где :

  • В это множество вершин
  • s s - исходная вершина
  • T s - целевая (или стоковая) вершина
  • AИкс,Y стоимость потока для края x -> y
  • еИкс,Yпоток края x -> yв оптимальном решении
  • d является необходимым потоком в приемнике (то есть спрос в T и производство в s)
  • СИкс,Y максимальная емкость края x -> y
digEmAll
источник
Хорошее линейное программирование :) К сожалению, большинство языков не имеют lpSolve... :(
Quintec
Это, к сожалению, правда ... Кстати, это не доступно на base-R, это пакет ... Я должен был попросить установить на TIO;)
digEmAll
По какой-то причине мне еще не удалось найти краткий способ изменения MinCostMaxFlow, чтобы он стал MinCostFlow ... мой мозг зажарен, лол, я хотел бы, чтобы была функция для этого на других языках, кроме mathematica
Quintec
@Quintec: вы имеете в виду конкретную реализацию (например, на определенном языке) MinCostMaxFlow?
digEmAll
Нет, мой алгоритм закодирован вручную
Quintec
1

Wolfram Language, 42 байта

FindMinimumCostFlow[#,1,VertexCount@#,#2]&

Тривиальное построение. Вскоре появится не встроенное решение.

lirtosiast
источник
Это будет через 6-8 недель? : P
Quintec
1

Python 3 + NetworkX , 137 байт

from networkx import*
def f(g,d,z='demand'):N=len(g)**.5//1;G=DiGraph(g);G.node[0][z]=-d;G.node[N-1][z]=d;return min_cost_flow_cost(G)

Нет ссылки TryItOnline, потому что на TIO не установлена ​​библиотека NetworkX

Принимает ввод графика в виде списка ребер с атрибутами емкости и веса, например:

[(0, 0, {'capacity': 0, 'weight': 0}), (0, 1, {'capacity': 3, 'weight': 1}), (0, 2, {'capacity': 2, 'weight': 1}), (0, 3, {'capacity': 3, 'weight': 2}), (0, 4, {'capacity': 2, 'weight': 1}), (1, 0, {'capacity': 3, 'weight': 1}), (1, 1, {'capacity': 0, 'weight': 0}), (1, 2, {'capacity': 5, 'weight': 1}), (1, 3, {'capacity': 3, 'weight': 2}), (1, 4, {'capacity': 3, 'weight': 3}), (2, 0, {'capacity': 2, 'weight': 1}), (2, 1, {'capacity': 5, 'weight': 1}), (2, 2, {'capacity': 0, 'weight': 0}), (2, 3, {'capacity': 4, 'weight': 2}), (2, 4, {'capacity': 5, 'weight': 2}), (3, 0, {'capacity': 3, 'weight': 2}), (3, 1, {'capacity': 3, 'weight': 2}), (3, 2, {'capacity': 4, 'weight': 2}), (3, 3, {'capacity': 0, 'weight': 0}), (3, 4, {'capacity': 4, 'weight': 3}), (4, 0, {'capacity': 2, 'weight': 1}), (4, 1, {'capacity': 3, 'weight': 3}), (4, 2, {'capacity': 5, 'weight': 2}), (4, 3, {'capacity': 4, 'weight': 3}), (4, 4, {'capacity': 0, 'weight': 0})]

Это версия кода, которую я использовал для проверки тестовых случаев.

Mego
источник