#include <iostream>
#include <vector>
#include <queue>
#include <map>
#include <string>
#include <climits>
#include <sstream>
#include <algorithm>
using namespace std;
// Helper function to parse time in "HH:MMAM/PM" format to minutes since midnight
int parse_time(const string& time_str) {
int hour = stoi(time_str.substr(0, 2));
int minute = stoi(time_str.substr(3, 2));
string meridian = time_str.substr(5, 2);
if (meridian == "Am" && hour == 12) {
hour = 0;
} else if (meridian == "Pm" && hour != 12) {
hour += 12;
}
return hour * 60 + minute;
}
class Flight {
public:
string source;
string destination;
int departure;
int arrival;
int price;
Flight(string source, string destination, string departure, string arrival, int price) {
this->source = source;
this->destination = destination;
this->departure = parse_time(departure);
this->arrival = parse_time(arrival);
this->price = price;
}
};
int find_cheapest_flight() {
// Read the number of flights
int num_flights;
cin >> num_flights;
vector<Flight> flights;
map<string, vector<Flight>> flight_map;
// Skip any potential newline after reading num_flights
cin.ignore();
// Read all the flight data
for (int i = 0; i < num_flights; i++) {
string line;
getline(cin, line);
// Skip any empty lines
if (line.empty()) {
continue;
}
stringstream ss(line);
string source, dest, departure, arrival;
int price;
ss >> source >> dest >> departure >> arrival >> price;
Flight flight(source, dest, departure, arrival, price);
flights.push_back(flight);
flight_map[source].push_back(flight);
}
// Read start and end cities
string start, end;
cin >> start >> end;
// Read the earliest departure and latest arrival time
string earliest_departure, latest_arrival;
cin >> earliest_departure >> latest_arrival;
int earliest_departure_time = parse_time(earliest_departure);
int latest_arrival_time = parse_time(latest_arrival);
// Priority queue for Dijkstra-like search: (cost, current_time, city)
priority_queue<tuple<int, int, string>, vector<tuple<int, int, string>>, greater<tuple<int, int, string>>> pq;
// Initially add flights that depart after the earliest departure time
for (const auto& flight : flight_map[start]) {
if (flight.departure >= earliest_departure_time && flight.arrival <= latest_arrival_time) {
pq.push(make_tuple(flight.price, flight.arrival, flight.destination));
}
}
// Dictionary to track the minimum cost to reach each city
map<string, int> min_cost;
map<string, int> arrival_time;
// Start the search
while (!pq.empty()) {
int cost, current_arrival;
string city;
tie(cost, current_arrival, city) = pq.top();
pq.pop();
// If we've reached the destination, print the cost
if (city == end) {
return cost;
}
// Skip if this city has already been reached with a cheaper cost or earlier arrival time
if (min_cost.find(city) != min_cost.end() && (cost > min_cost[city] || (cost == min_cost[city] && current_arrival >= arrival_time[city]))) {
continue;
}
// Record the minimum cost and arrival time for this city
min_cost[city] = cost;
arrival_time[city] = current_arrival;
// Explore all outgoing flights from the current city
for (const auto& flight : flight_map[city]) {
if (flight.departure >= current_arrival && flight.departure >= earliest_departure_time && flight.arrival <= latest_arrival_time) {
pq.push(make_tuple(cost + flight.price, flight.arrival, flight.destination));
}
}
}
// If we finished the while loop without reaching the destination city
return -1; // Impossible
}
int main() {
int result = find_cheapest_flight();
if (result == -1) {
cout << "Impossible" << endl;
} else {
cout << result << endl;
}
return 0;
}