Time Limit: 1000 mSec
Problem Description
In a small city called Iokh, a train service, Airport-Express, takes residents to the airport more quickly than other transports. There are two types of trains in Airport-Express, the Economy-Xpress and the Commercial-Xpress. They travel at different speeds, take different routes and have different costs. Jason is going to the airport to meet his friend. He wants to take the Commercial-Xpress which is supposed to be faster, but he doesn’t have enough money. Luckily he has a ticket for the Commercial-Xpress which can take him one station forward. If he used the ticket wisely, he might end up saving a lot of time. However, choosing the best time to use the ticket is not easy for him. Jason now seeks your help. The routes of the two types of trains are given. Please write a program to find the best route to the destination. The program should also tell when the ticket should be used.
Input
The input consists of several test cases. Consecutive cases are separated by a blank line. The first line of each case contains 3 integers, namely N, S and E (2 ≤ N ≤ 500,1 ≤ S,E ≤ N), which represent the number of stations, the starting point and where the airport is located respectively. There is an integer M (1 ≤ M ≤ 1000) representing the number of connections between the stations of the Economy-Xpress. The next M lines give the information of the routes of the Economy-Xpress. Each consists of three integers X, Y and Z (X,Y ≤ N,1 ≤ Z ≤ 100). This means X and Y are connected and it takes Z minutes to travel between these two stations. The next line is another integer K (1 ≤ K ≤ 1000) representing the number of connections between the stations of the Commercial-Xpress. The next K lines contain the information of the CommercialXpress in the same format as that of the Economy-Xpress. All connections are bi-directional. You may assume that there is exactly one optimal route to the airport. There might be cases where you MUST use your ticket in order to reach the airport.
Output
For each case, you should first list the number of stations which Jason would visit in order. On the next line, output ‘Ticket Not Used’ if you decided NOT to use the ticket; otherwise, state the station where Jason should get on the train of Commercial-Xpress. Finally, print the total time for the journey on the last line. Consecutive sets of output must be separated by a blank line.
Sample Input
Sample Output
1 2 4
2
5
题解:考虑枚举用哪个商业票,为什么这么想呢,因为堆优化Dijkstra复杂度(n+m)logn,乘上个K,如果没有多组数据的话应该是能过的,其实可以做到更好,分别从起点和终点跑两遍最短路,这样对于枚举的用商业票的那一段来说就可以常数时间内算出总费用,因为最短路一定是w(u, v) + dist[u](起点到u最短路) + dist2[v](v到终点最短路),这样问题就在O(K)时间内解决了。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define REP(i, n) for (int i = 1; i <= (n); i++) 6 #define sqr(x) ((x) * (x)) 7 8 const int maxn = 10000 + 10; 9 const int maxm = 20000 + 10; 10 const int maxs = 10000 + 10; 11 12 typedef long long LL; 13 typedef pair<int, int> pii; 14 typedef pair<double, double> pdd; 15 16 const LL unit = 1LL; 17 const int INF = 0x3f3f3f3f; 18 const LL mod = 1000000007; 19 const double eps = 1e-14; 20 const double inf = 1e15; 21 const double pi = acos(-1.0); 22 23 struct Edge 24 { 25 int to, w, next; 26 } edge[maxm]; 27 28 struct HeapNode 29 { 30 int dis, u; 31 bool operator<(const HeapNode &a) const 32 { 33 return dis > a.dis; 34 } 35 }; 36 37 int tot, head[maxn]; 38 int n, m, k; 39 int st, en; 40 41 void init() 42 { 43 tot = 0; 44 memset(head, -1, sizeof(head)); 45 } 46 47 void AddEdge(int u, int v, int w) 48 { 49 edge[tot].to = v; 50 edge[tot].w = w; 51 edge[tot].next = head[u]; 52 head[u] = tot++; 53 } 54 55 int dist[maxn], dist2[maxn]; 56 int pre[maxn], Next[maxn]; 57 bool vis[maxn]; 58 59 int Dijkstra() 60 { 61 memset(dist, INF, sizeof(dist)); 62 memset(vis, false, sizeof(vis)); 63 memset(pre, -1, sizeof(pre)); 64 priority_queue<HeapNode> que; 65 pre[st] = st; 66 dist[st] = 0; 67 que.push((HeapNode){0, st}); 68 while (!que.empty()) 69 { 70 HeapNode first = que.top(); 71 que.pop(); 72 int u = first.u; 73 if (vis[u]) 74 continue; 75 vis[u] = true; 76 for (int i = head[u]; i != -1; i = edge[i].next) 77 { 78 int v = edge[i].to; 79 if (dist[v] > dist[u] + edge[i].w) 80 { 81 pre[v] = u; 82 dist[v] = dist[u] + edge[i].w; 83 que.push((HeapNode){dist[v], v}); 84 } 85 } 86 } 87 return dist[en]; 88 } 89 90 void Dijkstra2() 91 { 92 memset(dist2, INF, sizeof(dist2)); 93 memset(vis, false, sizeof(vis)); 94 memset(Next, -1, sizeof(Next)); 95 priority_queue<HeapNode> que; 96 dist2[en] = 0; 97 Next[en] = en; 98 que.push((HeapNode){0, en}); 99 while (!que.empty()) 100 { 101 HeapNode first = que.top(); 102 que.pop(); 103 int u = first.u; 104 if (vis[u]) 105 continue; 106 vis[u] = true; 107 for (int i = head[u]; i != -1; i = edge[i].next) 108 { 109 int v = edge[i].to; 110 if (dist2[v] > dist2[u] + edge[i].w) 111 { 112 Next[v] = u; 113 dist2[v] = dist2[u] + edge[i].w; 114 que.push((HeapNode){dist2[v], v}); 115 } 116 } 117 } 118 } 119 120 int main() 121 { 122 ios::sync_with_stdio(false); 123 cin.tie(0); 124 //freopen("input.txt", "r", stdin); 125 //freopen("output.txt", "w", stdout); 126 bool ok = false; 127 while (cin >> n >> st >> en) 128 { 129 init(); 130 cin >> m; 131 int x, y, z; 132 for (int i = 0; i < m; i++) 133 { 134 cin >> x >> y >> z; 135 AddEdge(x, y, z); 136 AddEdge(y, x, z); 137 } 138 int Min = Dijkstra(); 139 //cout << "Min:" << Min << endl; 140 Dijkstra2(); 141 cin >> k; 142 int ansu = -1, ansv = -1; 143 for(int i = 0; i < k; i++) 144 { 145 cin >> x >> y >> z; 146 if(dist[x] + z + dist2[y] < Min) 147 { 148 Min = dist[x] + z + dist2[y]; 149 ansu = x, ansv = y; 150 } 151 if(dist[y] + z + dist2[x] < Min) 152 { 153 Min = dist[y] + z + dist2[x]; 154 ansu = y, ansv = x; 155 } 156 } 157 if(!ok) 158 ok = true; 159 else 160 cout << endl; 161 //cout << "Min:" << Min << endl; 162 if(ansu == -1 && ansv == -1) 163 { 164 int tmp = st; 165 while(tmp != en) 166 { 167 cout << tmp << " "; 168 tmp = Next[tmp]; 169 } 170 cout << en << endl; 171 cout << "Ticket Not Used" << endl; 172 cout << Min << endl; 173 } 174 else 175 { 176 int tmp = ansu; 177 stack<int> ans; 178 while(!ans.empty()) 179 ans.pop(); 180 while(tmp != st) 181 { 182 ans.push(tmp); 183 tmp = pre[tmp]; 184 } 185 ans.push(st); 186 while(!ans.empty()) 187 { 188 cout << ans.top() << " "; 189 ans.pop(); 190 } 191 tmp = ansv; 192 while (tmp != en) 193 { 194 cout << tmp << " "; 195 tmp = Next[tmp]; 196 } 197 cout << en << endl; 198 cout << ansu << endl; 199 cout << Min << endl; 200 } 201 } 202 return 0; 203 }