UVa 12661 - Funny Car Racing(Dijkstra)
阿新 • • 發佈:2018-08-28
time push_back cst urn mem printf 起點 show tro
註意你的賽車可以在道路關閉的時候在路口等待它打開。沒有道路連接同一個路口,但一對路口之間可能有多條道路。
你的任務是從s出發,盡早到達目的地t(1≤s,t≤n)。
鏈接:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4399
題意:
在一個賽車比賽中,賽道有n(n≤300)個路口和m(m≤50000)條單向道路。有趣的是:每條路都是周期性關閉的。
每條路用5個整數u, v, a, b, t表示(1≤u,v≤n,1≤a,b,t≤1e5),表示起點是u,終點是v,通過時間為t秒。
另外,這條路會打開a秒,然後關閉b秒,然後再打開a秒,依此類推。當比賽開始時,每條道路剛剛打開。
你的賽車必須在道路打開的時候進入該道路,並且在它關閉之前離開(可以在打開的瞬間進入,關閉的瞬間離開)。
註意你的賽車可以在道路關閉的時候在路口等待它打開。沒有道路連接同一個路口,但一對路口之間可能有多條道路。
你的任務是從s出發,盡早到達目的地t(1≤s,t≤n)。
分析:
本題是一道最短路問題,但又和普通的最短路問題不太相同:花費的總時間並不是經過的每條邊的通過時間之和,
還要加上在每個點等待的總時間。仍然調用標準的Dijkstra算法,
只是在計算一個結點u出發的邊權時要考慮d[u](即從s出發達到u的最早時刻)。計算邊權時分情況討論一下即可。
代碼:
1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4#include <vector> 5 using namespace std; 6 7 struct Edge { 8 int b, open, close, time; 9 }; 10 struct HeapNode { 11 int ver, dist; 12 bool operator < (const HeapNode& that) const { 13 return dist > that.dist; 14 } 15 }; 16 const int INF = 0x3f3f3f3f; 17 constint UP = 300 + 5; 18 int d[UP]; 19 bool done[UP]; 20 vector<Edge> edge[UP]; 21 22 int Dijkstra(int start, int finish) { 23 memset(d, INF, sizeof(d)); 24 memset(done, false, sizeof(done)); 25 d[start] = 0; 26 priority_queue<HeapNode> Q; 27 Q.push((HeapNode){start, 0}); 28 while(!Q.empty()) { 29 HeapNode f = Q.top(); Q.pop(); 30 int ver = f.ver; 31 if(ver == finish) return f.dist; 32 if(done[ver]) continue; 33 done[ver] = true; 34 for(int i = 0; i < edge[ver].size(); i++) { 35 Edge& b = edge[ver][i]; 36 int progress = d[ver] % (b.open + b.close); 37 if(progress + b.time <= b.open) { 38 if(d[b.b] > d[ver] + b.time) { 39 d[b.b] = d[ver] + b.time; 40 Q.push((HeapNode){b.b, d[b.b]}); 41 } 42 } else { 43 int need = d[ver] + b.time + b.open + b.close - progress; 44 if(d[b.b] > need) { 45 d[b.b] = need; 46 Q.push((HeapNode){b.b, need}); 47 } 48 } 49 } 50 } 51 return d[finish]; 52 } 53 54 int main() { 55 int n, m, start, finish; 56 for(int cases = 1; ~scanf("%d%d%d%d", &n, &m, &start, &finish); cases++) { 57 for(int i = 1; i <= n; i++) edge[i].clear(); 58 for(int L, R, a, b, t, i = 0; i < m; i++) { 59 scanf("%d%d%d%d%d", &L, &R, &a, &b, &t); 60 if(t > a) continue; 61 edge[L].push_back((Edge){R, a, b, t}); 62 } 63 printf("Case %d: %d\n", cases, Dijkstra(start, finish)); 64 } 65 return 0; 66 }
UVa 12661 - Funny Car Racing(Dijkstra)