26 using System.Collections.Generic;
65 public Func<Node, long>
Supply {
get;
private set; }
68 public Func<Arc, double>
Cost {
get;
private set; }
70 private double Epsilon;
75 private Node ArtificialNode;
76 private HashSet<Arc> ArtificialArcs;
82 private Dictionary<Arc, long> Tree;
84 private HashSet<Arc> Saturated;
86 private Dictionary<Node, double> Potential;
88 private IEnumerator<Arc> EnteringArcEnumerator;
95 Func<Arc, long> lowerBound = null, Func<Arc, long> upperBound = null,
96 Func<Node, long> supply = null, Func<Arc, double> cost = null)
100 UpperBound = upperBound ?? (x =>
long.MaxValue);
101 Supply = supply ?? (x => 0);
102 Cost = cost ?? (x => 1);
105 foreach (var arc
in graph.Arcs())
107 double x = Math.Abs(
Cost(arc));
108 if (x > 0 && x < Epsilon) Epsilon = x;
118 if (Saturated.Contains(arc))
return UpperBound(arc);
120 if (Tree.TryGetValue(arc, out result))
return result;
122 return result ==
long.MinValue ? 0 : result;
126 public IEnumerable<KeyValuePair<Arc, long>>
Forest
141 Dictionary<Node, long> excess =
new Dictionary<Node, long>();
144 Saturated =
new HashSet<Arc>();
149 if (g <
long.MaxValue) Saturated.Add(arc);
150 long flow =
Flow(arc);
151 excess[
Graph.
U(arc)] -= flow;
152 excess[
Graph.
V(arc)] += flow;
155 Potential =
new Dictionary<Node, double>();
157 ArtificialNode = MyGraph.AddNode();
158 Potential[ArtificialNode] = 0;
159 ArtificialArcs =
new HashSet<Arc>();
160 var artificialArcOf =
new Dictionary<Node, Arc>();
166 Potential[n] = (e > 0 ? -1 : 1);
167 ArtificialArcs.Add(arc);
168 artificialArcOf[n] = arc;
171 Tree =
new Dictionary<Arc, long>();
172 TreeSubgraph =
new Subgraph(MyGraph);
173 TreeSubgraph.EnableAllArcs(
false);
174 foreach (var kv
in artificialArcOf)
176 Tree[kv.Value] = Math.Abs(excess[kv.Key]);
177 TreeSubgraph.
Enable(kv.Value,
true);
181 EnteringArcEnumerator = MyGraph.
Arcs().GetEnumerator();
182 EnteringArcEnumerator.MoveNext();
185 private long ActualLowerBound(
Arc arc)
187 return ArtificialArcs.Contains(arc) ? 0 :
LowerBound(arc);
190 private long ActualUpperBound(Arc arc)
192 return ArtificialArcs.Contains(arc) ?
196 private double ActualCost(Arc arc)
202 private class RecalculatePotentialDfs : Dfs
206 protected override void Start(out Direction direction)
211 protected override bool NodeEnter(Node node, Arc arc)
213 if (arc ==
Arc.Invalid)
214 Parent.Potential[node] = 0;
217 Node other = Parent.MyGraph.Other(arc, node);
218 Parent.Potential[node] = Parent.Potential[other] +
219 (node == Parent.MyGraph.V(arc) ? Parent.ActualCost(arc) : -Parent.ActualCost(arc));
225 private class UpdatePotentialDfs : Dfs
230 protected override void Start(out Direction direction)
235 protected override bool NodeEnter(Node node, Arc arc)
237 Parent.Potential[node] += Diff;
243 private static ulong MySubtract(
long a,
long b)
245 if (a ==
long.MaxValue || b ==
long.MinValue)
return ulong.MaxValue;
246 return (ulong)(a - b);
256 Arc firstArc = EnteringArcEnumerator.Current;
258 double enteringReducedCost =
double.NaN;
259 bool enteringSaturated =
false;
262 Arc arc = EnteringArcEnumerator.Current;
263 if (!Tree.ContainsKey(arc))
265 bool saturated = Saturated.Contains(arc);
266 double reducedCost = ActualCost(arc) - (Potential[MyGraph.
V(arc)] - Potential[MyGraph.
U(arc)]);
267 if ((reducedCost < -Epsilon && !saturated) ||
268 (reducedCost > Epsilon && (saturated || ActualLowerBound(arc) ==
long.MinValue)))
271 enteringReducedCost = reducedCost;
272 enteringSaturated = saturated;
278 if (!EnteringArcEnumerator.MoveNext())
280 EnteringArcEnumerator = MyGraph.
Arcs().GetEnumerator();
281 EnteringArcEnumerator.MoveNext();
283 if (EnteringArcEnumerator.Current == firstArc)
break;
291 foreach (var arc
in ArtificialArcs)
if (
Flow(arc) > 0)
297 new RecalculatePotentialDfs() { Parent =
this }.Run(TreeSubgraph);
305 Node u = MyGraph.
U(enteringArc), v = MyGraph.
V(enteringArc);
306 List<Arc> forwardArcs =
new List<Arc>();
307 List<Arc> backwardArcs =
new List<Arc>();
309 foreach (var n
in pathu.Nodes())
311 var arc = pathu.NextArc(n);
312 (MyGraph.
U(arc) == n ? forwardArcs : backwardArcs).Add(arc);
316 ulong delta = enteringReducedCost < 0 ? MySubtract(ActualUpperBound(enteringArc),
Flow(enteringArc)) :
317 MySubtract(
Flow(enteringArc), ActualLowerBound(enteringArc));
318 Arc exitingArc = enteringArc;
319 bool exitingSaturated = !enteringSaturated;
320 foreach (var arc
in forwardArcs)
322 ulong q = enteringReducedCost < 0 ? MySubtract(ActualUpperBound(arc), Tree[arc]) :
323 MySubtract(Tree[arc], ActualLowerBound(arc));
325 { delta = q; exitingArc = arc; exitingSaturated = (enteringReducedCost < 0); }
327 foreach (var arc
in backwardArcs)
329 ulong q = enteringReducedCost > 0 ? MySubtract(ActualUpperBound(arc), Tree[arc]) :
330 MySubtract(Tree[arc], ActualLowerBound(arc));
332 { delta = q; exitingArc = arc; exitingSaturated = (enteringReducedCost > 0); }
336 long signedDelta = 0;
340 signedDelta = enteringReducedCost < 0 ? (long)delta : -(
long)delta;
341 foreach (var arc
in forwardArcs) Tree[arc] += signedDelta;
342 foreach (var arc
in backwardArcs) Tree[arc] -= signedDelta;
346 if (exitingArc == enteringArc)
348 if (enteringSaturated) Saturated.Remove(enteringArc);
else Saturated.Add(enteringArc);
353 Tree.Remove(exitingArc);
354 TreeSubgraph.
Enable(exitingArc,
false);
355 if (exitingSaturated) Saturated.Add(exitingArc);
358 double diff = ActualCost(enteringArc) - (Potential[v] - Potential[u]);
359 if (diff != 0)
new UpdatePotentialDfs() { Parent =
this, Diff = diff }.
360 Run(TreeSubgraph,
new Node[] { v });
363 Tree[enteringArc] =
Flow(enteringArc) + signedDelta;
364 if (enteringSaturated) Saturated.Remove(enteringArc);
365 TreeSubgraph.
Enable(enteringArc,
true);