• No results found

An even better implementation of the Edmonds Karp’s algorithm is to avoid using the O(V 2 ) Adjacency Matrix to store residual capacity of each edge. A better way is to store

In document Competitive Programming 2 (Page 119-122)

Profile of Algorithm Inventors

Exercise 4.6.3.3: An even better implementation of the Edmonds Karp’s algorithm is to avoid using the O(V 2 ) Adjacency Matrix to store residual capacity of each edge. A better way is to store

// inside int main()

// set up the 2d AdjMat ‘res’, ‘s’, and ‘t’ with appropriate values

mf = 0; // mf stands for max_flow

while (1) { // O(VE^2) (actually O(V^3E) Edmonds Karp’s algorithm f = 0;

// run BFS, compare with the original BFS shown in Section 4.2.2 vi dist(MAX_V, INF); dist[s] = 0; queue<int> q; q.push(s);

p.assign(MAX_V, -1); // record the BFS spanning tree, from s to t!

while (!q.empty()) {

int u = q.front(); q.pop();

if (u == t) break; // immediately stop BFS if we already reach sink t for (int v = 0; v < MAX_V; v++) // note: this part is slow

if (res[u][v] > 0 && dist[v] == INF)

dist[v] = dist[u] + 1, q.push(v), p[v] = u; // three lines in one!

}

augment(t, INF); // find the minimum edge weight ‘f’ along this path, if any if (f == 0) break; // we cannot send any more flow (‘f’ = 0), terminate mf += f; // we can still send a flow, increase the max flow!

}

printf("%d\n", mf); // this is the max flow value

Example codes: ch4 08 edmonds karp.cpp; ch4 08 edmonds karp.java

Exercise 4.6.3.2: The main weakness of the simple code shown in this section is that enumerating the neighbors of a vertex takes O(V ) instead of O(k) (where k is the number of neighbors of that vertex). We also do not need vi dist as bitset to flag whether a vertex has been visited or not is sufficient. Now modify the Edmonds Karp’s implementation so that it really achieves its O(V E2) time complexity.

Exercise 4.6.3.3: An even better implementation of the Edmonds Karp’s algorithm is to avoid using the O(V2) Adjacency Matrix to store residual capacity of each edge. A better way is to store the actual flow and capacity (not just the residual) of each edge as an O(V +E) modified Adjacency List. We can derive the residual of an edge from the original capacity of that edge minus the flow of that edge. Now, modify the implementation again!

Exercise 4.6.3.4: Even the best Edmonds Karp’s implementation still runs in O(V E2). Although it should be sufficient to solve most Max Flow problems in today’s programming contests, some harder Max Flow problems need a faster solution. Explore the Internet to study and implement the O(V2E) Dinic’s algorithm which is theoretically faster as E >> V in flow graph.

Next, we show an example of modeling the flow (residual) graph of UVa 259 - Software Allocation19. The abridged version of this problem is as follows: You are given up to 26 app(lication)s (labeled

‘A’ to ‘Z’), up to 10 computers (numbered from 0 to 9), the number of persons who brought in each application that day (one digit positive integer, or [1..9]), the list of computers that a particular

19Actually this problem has small input size (we only have 26 + 10 = 36 vertices plus 2 more (source and sink)) which make this problem still solvable with recursive backtracking.

4.6. MAXIMUM FLOW  Steven & Felixc

application can run, and the fact that each computer can only run one application that day. Your task is to determine whether an allocation (that is, a matching) of applications to computers can be done, and if so, generates a possible allocation. If no, simply print an exclamation mark ‘!’.

Figure 4.23: Residual Graph of UVa 259 [28]

The flow graph formulation is as shown in Figure 4.23. First we index the vertices from [0..37] as there are 26 + 10 + 2 spe-cial vertices = 38 vertices. The source ‘s’ is given index 0, the 26 possible apps are given indices from [1..26], the 10 possible com-puters are given indices from [27..36], and finally the sink ‘t’ is given index 37. Then, link apps to computers as mentioned in the problem description. Link source s to all apps and link all computers to sink t. We set all the edge weights to be 1 (this implies these edges can only be used once) except the

edges from source ‘s’ to apps (can be used several times). This is the key part of this flow graph.

The path from an app A to a computer B and finally to sink ‘t’ have weight 1 that corresponds to one matching between that particular app A and computer B. The problem says that there can be more than one (say, X) users bringing in a particular app A in a given day. To accommodate this, we have to set the capacity from source ‘s’ to this particular app A to X.

Once we have this flow graph, we can pass it to our Edmonds Karp’s implementation shown earlier to obtain the Max Flow mf. If mf is equal to the number of applicants brought in that day, then we have a solution, i.e. if we have X users bringing in app A, then X different paths (i.e.

matchings) from A to sink ‘t’ will have been found by the Edmonds Karp’s algorithm.

The actual app→ computer assignments can be found by simply checking the backward edges from computers (vertices 27 - 36) to apps (vertices 1 - 26). A backward edge (computer → app) in the residual matrix res will contain a value +1 if the corresponding forward edge (app→ computer) is selected in the paths that contribute to the Max Flow mf.

4.6.4 Other Applications

There are several other interesting applications/variants of the Max Flow problem. We discuss six examples here while some others are deferred until Section 4.7.4 (Bipartite Graph). Note that some tricks shown here may also be applicable to other graph problems.

Minimum Cut

Let’s define an s-t cut C = (S-component, T -component) as a partition of V ∈ G such that source s ∈ S-component and sink t ∈ T -component. Let’s also define a cut-set of C to be the set {(u, v) ∈ E | u ∈ S-component, v ∈ T -component} such that if all edges in the cut-set of C are removed, the Max Flow from s to t is 0 (i.e. s and t are disconnected). The cost of an s-t cut C is defined by the sum of the capacities of the edges in the cut-set of C. The Minimum Cut problem, often abbreviated as just Min Cut, is to minimize the amount of capacity of an s-t cut.

This problem is more general than finding bridges (see Section 4.2.1), i.e. in this case we can cut more than just one edge, but we want to do so in the least cost way. As with bridges, Min Cut has applications in ‘sabotaging’ networks.

The solution is simple: The by-product of computing Max Flow is Min Cut! Let’s see Figure 4.20.D. After Max Flow algorithm stops, we run graph traversal (DFS/BFS) from source s again.

All vertices that are still reachable from source s (vertex 0 and 2 in this case) belong to the S-component. All other unreachable vertices belong to the T -component (vertex 1 and 3 in this case).

All edges connecting S-component and T -component belong to the cut-set of C (edge 0-3 (capacity 30/flow 30/residual 0), 2-3 (5/5/0) and 2-1 (25/25/0) in this case). The Min Cut value is 30+5+25

= 60 = Max Flow value mf. This value is the minimum over all possible s-t cuts value.

4.6. MAXIMUM FLOW  Steven & Felixc

Multi-source Multi-sink Max Flow

Sometimes, we can have more than one source and/or more than one sink. However, this variant is no harder than the original Max Flow problem with a single source and a single sink. Create a super source ss and a super sink st. Connect ss with all s with infinite capacity and also connect all t with st with infinite capacity, then run the Edmonds Karp’s algorithm as per normal. FYI, we have seen this variant as exercise in Section 4.2.2 (Multi-Sources BFS).

Max Flow with Vertex Capacities

Figure 4.24: Vertex Splitting Technique

We can also have a Max Flow variant where the capacities are not just defined along the edges but also on the vertices. To solve this variant, we can use the vertex splitting technique. A weighted graph with a vertex weight can be converted into a more familiar one without a vertex weight by splitting each weighted vertex v to voutand vin, reassigning its incoming/outgoing edges to vout/vin, respectively and finally putting the original vertex v’s weight as the weight of edge (vout, vin). See Figure 4.24 for illustration. Then run the Edmonds Karp’s algorithm as per normal.

Maximum Independent Paths

The problem of finding the maximum number of independent paths from source s to sink t can be reduced to the Max Flow problem. Two paths are said to be independent if they do not share any vertex apart from s and t (vertex-disjoint). Solution: construct a flow network N = (V, E) from G with vertex capacities, where N is the carbon copy of G except that the capacity of each v∈ V is 1 (i.e. each vertex can only be used once) and the capacity of each e∈ E is also 1 (i.e. each edge can only be used once too). Then run the Edmonds Karp’s algorithm as per normal.

Maximum Edge-Disjoint Paths

Finding the maximum number of edge-disjoint paths from s to t is similar to finding maximum independent paths. The only difference is that this time we do not have any vertex capacity (i.e.

two edge-disjoint paths can still share the same vertex). See Figure 4.25 for a comparison between independent paths and edge-disjoint paths from s = 0 to t = 6.

Figure 4.25: Comparison Between the Max Independent Paths versus Max Edge-Disjoint Paths

4.6. MAXIMUM FLOW  Steven & Felixc

Min Cost (Max) Flow

The Min Cost Flow problem is the problem of finding the cheapest possible way of sending a certain amount of flow (usually the Max Flow) through a flow network. In this problem, every edge has two attributes: the flow capacity through this edge and the cost to use this edge.

Figure 4.26: An Example of Min Cost Max Flow (MCMF) Problem (from UVa 10594 [28]) Figure 4.26, left shows a (modified) instance of UVa 10594. Here, each edge has a uniform capacity of 10 units and a cost as shown in the edge label. We want to send 20 units of flow which can be satisfied by sending 10 units of flow A→ D with cost 1 × 10 = 10 (Figure 4.26, middle); plus another 10 units of flow A → B → D with cost (3 + 4) × 10 = 70 (Figure 4.26, right). The total cost is 10 + 70 = 80 and this is the minimum. Note that if we choose to send the 20 units of flow via A → D (10 units) and A → C → D instead (another 10 units), we incur a cost of 1× 10 + (3 + 5) × 10 = 10 + 80 = 90. This is higher than the optimal cost of 80.

The Min Cost (Max) Flow, or in short MCMF, can be solved by replacing BFS to find the shortest (in terms of number of hops) augmenting path in Edmonds Karp’s to Bellman Ford’s to find the shortest/cheapest (in terms of the path cost) augmenting path. The Dijkstra’s implementation variant shown in Section 4.4.3 can also be used as it can also handle negative edge weight that may appear when we cancel certain flow along backward edge.

Exercise 4.6.4.1: We have not shown any MCMF code in this section but instead we left the

In document Competitive Programming 2 (Page 119-122)

Outline

Related documents