There is a funny car racing in a city with n junctions and m directed roads.
The funny part is: each road is open and closed periodically. Each road is associate with two integers (a, b), that means the road will be open for a seconds, then closed for b seconds, then open for a seconds... All these start from the beginning of the race. You must enter a road when it's open, and leave it before it's closed again.
Your goal is to drive from junction s and arrive at junction t as early as possible. Note that you can wait at a junction even if all its adjacent roads are closed.
There will be at most 30 test cases. The first line of each case contains four integers n, m, s, t (1<=n<=300, 1<=m<=50,000, 1<=s,t<=n). Each of the next m lines contains five integers u, v, a, b, t (1<=u,v<=n, 1<=a,b,t<=105), that means there is a road starting from junction u ending with junction v. It's open for a seconds, then closed for b seconds (and so on). The time needed to pass this road, by your car, is t. No road connects the same junction, but a pair of junctions could be connected by more than one road.
For each test case, print the shortest time, in seconds. It's always possible to arrive at t from s.
3 2 1 31 2 5 6 32 3 7 7 63 2 1 31 2 5 6 32 3 9 5 6
Case 1: 20
Case 2: 9
题意:
给你N个点,M条边,每条边有开启时间l,关闭时间R和通过改变所需的时间t,该路开启时间持续 I 后 关闭,然后关闭时间持续R后开启,一直循环
然后给你一个起点S, 一个终点V, 求S到V所需的最短时间
方法:
用最短路即可求解,不过再在更新点i到起点的最短距离时做一下处理
PS: 做训练赛的时候我就想到这题用最短路应该就能做的,不过这题 是英文题,SO 我看错题目了。。。。
首先我就看到两点之间可能有多条边,然后因为题目描述中图的边是路, 所以我以为边是双向的, 其实是单向边
代码:
#include <stdio.h> #include <string.h> #include <algorithm> #include <limits.h> using namespace std; #define maxn 300 #define maxm 50000 struct node { int x, y, l, r, s; }edge[2*maxm+5]; int sum[maxn+5]; int vis[maxn+5]; int dis[maxn+5]; int n, m, be, end; int cmp(node x, node y) { return x.x< y.x; } void dij() { for(int c= 1; c<= n; c++) { int min= INT_MAX; int pos= -1; for(int i= 1; i<= n; i++) if(dis[i]< min && !vis[i]) { min= dis[i]; pos= i; } if(min== INT_MAX) break; vis[pos]= 1; //加入集合中 for(int i= sum[pos-1]+1; i<= sum[pos]; i++) { if(!vis[edge[i].y] && edge[i].l>= edge[i].s) { int lt= edge[i].l - dis[pos]%(edge[i].l + edge[i].r); //路开启所剩的时间 int cost; //通过这条路需要的时间 if(lt>= edge[i].s) //剩余时间足够通过这条路 cost= edge[i].s; else cost= lt + edge[i].r + edge[i].s;// 时间不够等待下次路开启 if(dis[pos]+ cost < dis[edge[i].y]) dis[edge[i].y]= dis[pos] + cost; //更新最短路 } } } } int main() { int T= 0; while(scanf("%d %d %d %d",&n,&m,&be,&end)!=EOF) { int u, v, a, b, t; memset(sum, 0, sizeof(sum)); for(int i= 1; i<= m; i++) { scanf("%d %d %d %d %d",&u, &v, &a, &b, &t); edge[i]= (node){u, v, a, b, t}; // edge[i+m]= (node){v, u, a, b, t}; sum[u]++; //是单向边不是双向边 // sum[v]++; } // sort(edge+1, edge+2*m+1, cmp); sort(edge+1, edge+m+1, cmp); for(int i= 2; i<= n; i++) sum[i]= sum[i] + sum[i-1]; for(int i= 1; i<= n; i++) dis[i]= 123456789; for(int i= sum[be-1]+1; i<= sum[be]; i++) { if(edge[i].l>= edge[i].s && dis[edge[i].y]> edge[i].s) //时间够通过这条道路 dis[edge[i].y]= edge[i].s; } memset(vis, 0, sizeof(vis)); vis[be]= 1; //标记起点已经走过 dij(); T++; printf("Case %d: %d\n",T,dis[end]); } return 0; }