I have a graph-based travel system where each city has two stations: a bus station and a train station. Each station is represented as a node (Node), and each connection/departure is represented as an edge (Edge) that may contain departure time, duration, cost, and type (e.g. bus or train). I use DFS to find all possible paths from the starting node to the destination city.
Here is the problem:
I specify a departureTime, for example 06:00 (converted to minutes), which is passed as the starting time to DFS. This is supposed to simulate the earliest time the traveler can start.
Now, let's say the first available departure is at 13:00. I don’t want the algorithm to count the time from 06:00 to 13:00 as waiting time. I only want waiting time between transfers (e.g. when changing from one departure to another).
Is there a clean way to handle this in DFS? Here's what I currently do:
When adding the first departure to the path, I store its time as firstDepartureTime.
Then I compute the total time as lastArrivalTime - firstDepartureTime.
Is this a good approach? Or is there a better way to ignore the initial idle time and only calculate waiting time between connections?
If I specify:
departureTime = timeStringToMinutes("06:00");
And the first edge (departure) available is at 13:00, and then another connection at 15:00, I want:
total waiting time = 15:00 - 13:00 = 2 hours (only this counts),
NOT 13:00 - 06:00 + 2 hours.
private static void dfs(Node current, String targetCity, Path currentPath, List<Path> allPaths, Set<Node> visited, Node previousNode, int previousArrivalTime) {
if (current.getCityName().equals(targetCity)) {
Path newPath = new Path(currentPath);
if (newPath.firstDepartureTime != -1) {
newPath.totalTime = previousArrivalTime - newPath.firstDepartureTime;
}
allPaths.add(newPath);
return;
}
visited.add(current);
for (Edge edge : current.neighbors) {
Node next = edge.getDestinationStation();
if (visited.contains(next))
continue;
int additionalCost = (edge.getDeparture() != null) ? edge.getDeparture().getPrice() : 0;
int duration = (edge.getDeparture() != null) ? edge.getDeparture().getDuration() : edge.getWeight();
int additionalTransfers = 0;
if (previousNode != null) {
boolean cityChanged = previousNode != null
&& !current.getCityName().equals(targetCity)
&& !current.getCityName().equals(previousNode.getCityName());
if (cityChanged) {
additionalTransfers = 1;
}
}
int waiting = 0;
int nextArrivalTime;
if (edge.getDeparture() != null) {
int edgeDepartureTime = timeStringToMinutes(edge.getDeparture().getDepartureTime());
int minTransferTime = edge.getDeparture().getMinimalWaitingTime();
if (edgeDepartureTime < previousArrivalTime + minTransferTime)
continue;
if (currentPath.edges.isEmpty()) {
currentPath.firstDepartureTime = edgeDepartureTime;
waiting = 0;
} else {
waiting = edgeDepartureTime - previousArrivalTime;
}
nextArrivalTime = edgeDepartureTime + edge.getDeparture().getDuration();
} else {
nextArrivalTime = previousArrivalTime + duration;
}
int additionalTime = duration + waiting;
currentPath.edges.add(edge);
currentPath.totalCost += additionalCost;
currentPath.totalTime += additionalTime;
currentPath.transferCount += additionalTransfers;
dfs(next, targetCity, currentPath, allPaths, visited, current, nextArrivalTime);
currentPath.edges.remove(currentPath.edges.size() - 1);
currentPath.totalCost -= additionalCost;
currentPath.totalTime -= additionalTime;
currentPath.transferCount -= additionalTransfers;
}
visited.remove(current);
}
if f(A,B)<λ(B) then λ(B)=f(A,B)). In 99% of Dijkstra algorithm taught, that f(A,B) is λ(A)+val(A,B). But in reality any f(A,B) such as f(A,B)>f(A) is sufficient so that DIjkstra can be proven to find the optimal solution.