// Railroads (铁路) // PC/UVa IDs: 111004/10039, Popularity: C, Success rate: average Level: 3 // Verdict: Accepted // Submission Date: 2011-10-05 // UVa Run Time: 0.392s // // 版权所有(C)2011,邱秋。metaphysis # yeah dot net // // [Problem Description] // Tomorrow morning Jill must travel from Hamburg to Darmstadt to compete in the // regional programming contest. Since she is afraid of arriving late and being // excluded from the contest, she is looking for the train which gets her to // Darmstadt as early as possible. However, she dislikes getting to the station // too early, so if there are several schedules with the same arrival time then // she will choose the one with the latest departure time. // // Jill asks you to help her with her problem. You are given a set of railroad // schedules from which you must compute the train with the earliest arrival time // and the fastest connection from one location to another. Fortunately, Jill is // very experienced in changing trains and can do this instantaneously, i.e., in // zero time! // // [Input] // The very first line of the input gives the number of scenarios. Each scenario // consists of three parts. The first part lists the names of all cities connected // by the railroads. It starts with a number 1 < C <= 100, followed by C lines // containing city names. All names consist only of letters. // // The second part describes all the trains running during a day. It starts with // a number T <= 1,000 followed by T train descriptions. Each of them consists // of one line with a number ti <= 100 and then ti more lines, each with a time // and a city name, meaning that passengers can get on or off the train at that // time at that city. // // The final part consists of three lines: the first containing the earliest // possible starting time, the second the name of the city where she starts, and // the third with the destination city. The start and destination cities are always // different. // // [Output] // For each scenario print a line containing ``Scenario i'', where i is the // scenario number starting from 1. // // If a connection exists, print the two lines containing zero padded timestamps // and locations as shown in the example. Use blanks to achieve the indentation. // If no connection exists on the same day (i.e., arrival before midnight), print // a line containing ``No connection''. // // Print a blank line after each scenario. // // [Sample Input] // 2 // 3 // Hamburg // Frankfurt // Darmstadt // 3 // 2 // 0949 Hamburg // 1006 Frankfurt // 2 // 1325 Hamburg // 1550 Darmstadt // 2 // 1205 Frankfurt // 1411 Darmstadt // 0800 // Hamburg // Darmstadt // 2 // Paris // Tokyo // 1 // 2 // 0100 Paris // 2300 Tokyo // 0800 // Paris // Tokyo // // [Sample Output] // Scenario 1 // Departure 0949 Hamburg // Arrival 1411 Darmstadt // // Scenario 2 // No connection // // [解题方法] // 题意需要求最早到达的最晚出发路线,从题目所给条件可以建模成有向图,然后从给定城市寻找到目标城市的 // 所有通路,这个可以通过宽度优先遍历来获得,与 UVa 10187 From Dusk till Dawn 类似,然后再比 // 较出发时间和到达时间,得到正确答案,当数据量较少时,可以很快得到正确结果,但是当火车列数和城市数 // 较多时,则因大量计算无法 AC,故用动态规划来加速。设立一个二维数组,表示到达时间为 T ,到达城市为 // C 时的最早出发时间,根据每个城市的路线情况来更新这个二维数组的值,最后从中间寻找是否有通路,若有 // 通路,则找出其最晚出发时间。 #include <iostream> #include <iomanip> #include <algorithm> #include <vector> #include <map> using namespace std; #define MAXV 100 #define MAXTIME 2400 #define NO_CONNECTION (-1) struct edge { int departure; int arrival; int to; bool operator<(const edge &e) const { return departure < e.departure; } }; vector < edge > edges[MAXV]; // 缓存:到达时间为 T,到达城市为 C 的最晚出发时间。 int cache[MAXTIME][MAXV]; // DP 搜索。 void search(int tdeparture, int from, int to, string cstart, string cdestination) { edge e; // 初始化缓存。 for (int i = 0; i < MAXTIME; i++) for (int j = 0; j < MAXV; j++) cache[i][j] = NO_CONNECTION; // 排序,将出发时间早的排在前面,可以减少一些后续比较时的运行时间,可根据情况选用。 for (int i = 0; i < MAXV; i++) sort(edges[i].begin(), edges[i].end()); // 设定初始条件。 for (int i = 0; i < edges[from].size(); i++) { e = edges[from][i]; if (e.departure < tdeparture) continue; // 更新缓存信息。 cache[e.arrival][e.to] = max(cache[e.arrival][e.to], e.departure); } // 动态规划。 for (int i = 0; i < MAXTIME; i++) for (int j = 0; j < MAXV; j++) { // 若为 NO_CONNECTION,不需处理。 if (cache[i][j] == NO_CONNECTION) continue; for (int k = edges[j].size() - 1; k >= 0; k--) { // 如果当前时间晚于此城市所有路线的最晚出发时间,则不可能在 // 当天再乘坐火车前往其他城市。 if (i > edges[j][k].departure) break; // 路线到达下一城市的时间。 int arrival = edges[j][k].arrival; // 路线到达的下一城市。 int next = edges[j][k].to; // 更新到达时间为 arrival,到达城市为 next 时的最晚出发时间。 cache[arrival][next] = max(cache[arrival][next], cache[i][j]); } } // 查找是否存在路线。 for (int i = 0; i < MAXTIME; i++) if (cache[i][to] != NO_CONNECTION) { cout << "Departure " << setw(4) << setfill('0'); cout << cache[i][to] << " " << cstart << endl; cout << "Arrival " << setw(4) << setfill('0'); cout << i << " " << cdestination << endl; return; } cout << "No connection" << endl; } int main(int ac, char *av[]) { int output = 1, cases, ncities, routes, nstations; string city; int tprevious, tcurrent, tdeparture; string cprevious, ccurrent, cstart, cdestination; cin >> cases; while (cases--) { // 读入城市名。 map < string, int > cities; cin >> ncities; for (int c = 0; c < ncities; c++) { cin >> city; cities[city] = c; edges[c].clear(); } // 建有向图。 cin >> routes; for (int c = 1; c <= routes; c++) { cin >> nstations; for (int m = 1; m <= nstations; m++) { cin >> tcurrent >> ccurrent; if (m > 1) edges[cities[cprevious]].push_back( (edge){tprevious, tcurrent, cities[ccurrent]}); tprevious = tcurrent; cprevious = ccurrent; } } cout << "Scenario " << output++ << endl; // 读入出发时间,出发城市和终点城市。 cin >> tdeparture >> cstart >> cdestination; // 使用动态规划找到从出发城市到终点城市最晚出发最早到达时间。 search(tdeparture, cities[cstart], cities[cdestination], cstart, cdestination); cout << endl; } return 0; }