Content deleted Content added
m LanguageTool: typo fix |
mNo edit summary |
||
Line 1:
In [[mathematical optimization]], the '''
The
The
==Concepts==
Line 19:
::{{nowrap|∑<sub>''v'' ∈ ''V''</sub> ''f''(''v'', ''u'') {{=}} 0 ∀''u'' ∈ ''V'' \ {''s'', ''t''}}}
The
:;Nonnegative excesses:
Line 28:
For each {{nowrap|(''u'', ''v'') ∈ ''V'' × ''V''}}, denote its ''residual capacity'' by {{nowrap|''c<sub>f</sub>''(''u'', ''v'') {{=}} ''c''(''u'', ''v'') − ''f''(''u'', ''v'')}}. The residual network of ''G'' with respect to a preflow ''f'' is defined as {{nowrap|''G<sub>f</sub>''(''V'', ''E<sub>f</sub>'')}} where {{nowrap|''E<sub>f</sub>'' {{=}} {(''u'', ''v'') {{!}} ''u'', ''v'' ∈ ''V'' ∧ ''c<sub>f</sub>''(''u'', ''v'') > 0}}}. If there is no path from any active vertex to ''t'' in {{nowrap|''G<sub>f</sub>''}}, the preflow is called ''maximum''. In a maximum preflow, {{nowrap|''e''(''t'')}} is equal to the value of a maximum flow; if ''T'' is the set of vertices from which ''t'' is reachable in {{nowrap|''G<sub>f</sub>''}}, and {{nowrap|''S'' {{=}} ''V'' \ ''T''}}, then {{nowrap|(''S'', ''T'')}} is a [[Max-flow min-cut theorem|minimum ''s''-''t'' cut]].
The
:;Valid labeling
Line 66:
To see that a relabel operation on vertex ''u'' preserves the validity of {{nowrap|''h''(''u'')}}, notice that this is trivially guaranteed by definition for the out-edges of ''u'' in {{nowrap|''G<sub>f</sub>''}}. For the in-edges of ''u'' in the {{nowrap|''G<sub>f</sub>''}}, the increased {{nowrap|''h''(''u'')}} can only satisfy the constraints less tightly, not violate them.
==The generic
===Description===
Line 73:
After initialization, the algorithm repeatedly executes an applicable push or relabel operation until no such operations apply, at which point the preflow has been converted into a maximum flow.
generic-
create a preflow f that saturates all out-edges of s
let h[u] = 0 ∀v ∈ V
Line 90:
==Practical implementations==
While the generic
==="Current-edge" data structure and discharge operation===
Line 109:
===Active vertex selection rules===
Definition of the discharge operation reduces the
====FIFO selection rule====
The [[FIFO]]
The algorithm has {{nowrap|''O''(''V''<sup>3</sup>)}} time complexity.
====Relabel-to-front selection rule====
The relabel-to-front
The algorithm also has {{nowrap|''O''(''V''<sup>3</sup>)}} time complexity.
====Highest label selection rule====
The highest-label
The algorithm has {{nowrap|''O''(''V''<sup>2</sup>{{sqrt|''E''}})}} time complexity. If the lowest-label selection rule is used instead, the time complexity becomes {{nowrap|''O''(''V''<sup>2</sup>''E'')}}.<ref name="ahuja97"/>
===Implementation techniques===
Although in the description of the generic
The algorithm is typically separated into two phases. Phase one computes a maximum preflow by discharging only active vertices whose heights are below ''n''. Phase two converts the maximum preflow into a maximum flow by returning excess flow that cannot reach ''t'' to ''s''. It can be shown that phase two has {{nowrap|''O''(''VE'')}} time complexity regardless of the order of push and relabel operations and is therefore dominated by phase one. Alternatively, it can be implemented using flow decomposition.<ref name="amo93"/>
Line 138:
#include <stdlib.h>
#include <stdio.h>
#define NODES 6
#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
#define INFINITE 10000000
void push(const int * const * C, int ** F, int *excess, int u, int v) {
int send = MIN(excess[u], C[u][v] - F[u][v]);
Line 150:
excess[v] += send;
}
void relabel(const int * const * C, const int * const * F, int *height, int u) {
int v;
Line 161:
}
};
void discharge(const int * const * C, int ** F, int *excess, int *height, int *seen, int u) {
while (excess[u] > 0) {
Line 167:
int v = seen[u];
if ((C[u][v] - F[u][v] > 0) && (height[u] > height[v])){
}
else
} else {
relabel(C, F, height, u);
Line 177:
}
}
void moveToFront(int i, int *A) {
int temp = A[i];
Line 186:
A[0] = temp;
}
int pushRelabel(const int * const * C, int ** F, int source, int sink) {
int *excess, *height, *list, *seen, i, p;
excess = (int *) calloc(NODES, sizeof(int));
height = (int *) calloc(NODES, sizeof(int));
seen = (int *) calloc(NODES, sizeof(int));
list = (int *) calloc((NODES-2), sizeof(int));
for (i = 0, p = 0; i < NODES; i++){
if((i != source) && (i != sink)) {
Line 202:
}
}
height[source] = NODES;
excess[source] = INFINITE;
for (i = 0; i < NODES; i++)
push(C, F, excess, source, i);
p = 0;
while (p < NODES - 2) {
Line 223:
for (i = 0; i < NODES; i++)
maxflow += F[source][i];
free(list);
free(seen);
free(height);
free(excess);
return maxflow;
}
void printMatrix(const int * const * M) {
int i,j;
Line 241:
}
}
int main(void) {
int **flow, **capacities, i;
Line 250:
capacities[i] = (int *) calloc(NODES, sizeof(int));
}
//Sample graph
capacities[0][1] = 2;
Line 260:
capacities[3][5] = 7;
capacities[4][5] = 4;
printf("Capacity:\n");
printMatrix(capacities);
printf("Max Flow:\n%d\n", pushRelabel(capacities, flow, 0, 5));
printf("Flows:\n");
printMatrix(flow);
return 0;
}
|