I am trying to determine an efficient, maximum flow algorithm using a directed graph where, given a list of n flights (where each entry has the starting city, ending city, departure time, arrival time, and capacity of the flight), will route as many people as possible starting from city A and ending at city B. I also want to be able to return the set of flights that can be taken such that the maximum possible amount of people will get to city B from city A. I think that it can just be an implementation of the Ford-Fulkerson algorithm, or something similar, but I am having trouble being able to transform this schedule into a max-flow instance in an efficient way, and specifically what the pseudocode of said algorithm would look like after having done so.
1 Answers
The algorithm you're thinking about would to the trick, but the graph is it set to work on must be constructed properly.
Your issue here is timing. Let's say You want to people from A
to C
by 14:00 and we have a total of 4 flights:
Flight 1: A -> B, 10:00 -> 11:00, Cap. 100
Flight 2: A -> B, 11:00 -> 12:00, Cap. 100
Flight 3: B -> C, 11:30 -> 12:30, Cap. 100
Flight 4: B -> C, 12:30 -> 13:30, Cap. 100
You can see here that you could fill all flights and get 200 from A
to C
in time, but constructing the graph needs to take the time into account.
What I suggest is that you don't have one node to represent B
, but rather have a few of them:
(B, 11:00)
- B
at 11:00.
(B, 12:00)
- B
at 12:00.
(B, 12:30)
- when flight #3 departs.
(B, 13:30)
- when flight #4 departs.
Any flight that can leave from B
will be added to the graph once, starting from the relevant B
node.
B
nodes are connected to other B
nodes in an edge with infinite capacity in the order of the time moving forwards. This allows passengers to "wait" between different times in B
.
This example would end up with the following list of edges:
// Flight edges
[(A, 10:00)
, (B, 11:00)
], Cap. 100
[(A, 11:00)
, (B, 12:00)
], Cap. 100
[(B, 11:30)
, (C, 12:00)
], Cap. 100
[(B, 12:30)
, (C, 13:00)
], Cap. 100
// Waiting edges
[(B, 11:00)
, (B, 11:30)
], Cap. infinite
[(B, 11:30)
, (B, 12:00)
], Cap. infinite
[(B, 12:00)
, (B, 12:30)
], Cap. infinite

- 2,308
- 2
- 26
- 39
-
I don't really mind about getting people to city C in your example by a specific time; I am only interested in getting as many people there as possible, as well as returning the set of flights that the people should take so that as many of them as possible can travel to city C. – honethecode265 Nov 12 '20 at 06:49
-
Shouldn't your waiting edges table be all letter 'B' nodes in this example? Could this perhaps be simplified to just links to the next relevant time? i.e. 11:00 -> 11:30 -> 12:00 -> 12:30 so every arrival and departure time at an airport is captured as a node and they are linked in a linear time ordered chain. – Ian Mercer Nov 12 '20 at 07:11
-
@IanMercer This is what I was thinking, to ensure a connected flight is actually possible from city A to every other city in our constructed graph (including to city C). The only problem is a way to do this efficiently, given just a list of flights in any order. I thought maybe a nested for loop would be necessary to compare every flight, which works, but this is obviously not the most efficient way. – honethecode265 Nov 12 '20 at 07:25
-
@IanMercer - thanks for both remarks. I've updated my answer accordingly. – shapiro yaacov Nov 12 '20 at 07:56
-
@honethecode265 - my solution will isn't so much about when people get to `C`, but more about they don't get a flight that leaves before they arrive. Hope this idea is useful – shapiro yaacov Nov 12 '20 at 07:57
-
@shapiroyaacov okay, but how exactly would you implement this efficiently? I still think a nested loop through the list of flights is somewhat necessary; although I think a linear search may be possible, and somehow storing the city you are currently looking at with each linear search of the flight schedule. – honethecode265 Nov 12 '20 at 16:25
-
@honethecode265 implementation is fairly easy. You start with a list of edges (flights). For each one, you add an edge to your graph and if required, the nodes at the ends of them. When adding a node at place `X` time `T` you also keep a list (or min heap) of all `T`s of `X`. Once all *flight* edges have been added, add the *waiting* edges. Done. – shapiro yaacov Nov 12 '20 at 18:57
-
@shapiroyaacov Do you have a visual example to runs through this step by step, including flights in the schedule that go from A-B and B back to A? You don't have to if you don't want to, but I am still struggling to understand how your implementation works. Like, how would we determine when it is not possible to add a flight to the graph at all? – honethecode265 Nov 12 '20 at 21:37
-
@honethecode265 I don't have anything like that. Regarding a flight that has no relevance - well, there would be no edge that gets to that node. Example: if `(B, 08:00)` is the origin for an edge there would be no incoming edge into that node in the example we have above... – shapiro yaacov Nov 12 '20 at 21:54
-
@shapiroyaacov Wouldn't we have to have a min-heap for every starting city in the schedule, to store their departure times and the city the flight arrived at? – honethecode265 Nov 12 '20 at 22:21