链接:
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 const int 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 }
原文地址:https://www.cnblogs.com/hkxy125/p/9545368.html
时间: 2024-10-30 04:31:50