UVa

先上题目:

12661 Funny Car Racing
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.
Input
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.
Output
For each test case, print the shortest time, in seconds. It’s always possible to arrive at t from s.
Sample Input
3 2 1 3
1 2 5 6 3
2 3 7 7 6
3 2 1 3
1 2 5 6 3
2 3 9 5 6
Sample Output
Case 1: 20
Case 2: 9

  题意:给出一个有向图,每条边都有三个值,打开时间间隔,关闭时间间隔,通过它需要多少时间,路的开关是循环往复的。给你起点和终点,问你最少需要多少时间才可以从起点到达终点(保证一定存在这种路)。

  这其实是求最短路,用DIJ求最短路,然后对于从某个点开始可以到达的下一个点,在分析是否需要更新的时候,需要判断当前时刻路开了没有,如果开了看看够不够时间过去,然后根据这些情况更新最小值就可以了。这里需要注意的东西就是这事有向图不是无向图。

 

上代码:

 

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define MAX 50002
 5 #define ll long long
 6 #define INF (((ll)1)<<60)
 7 using namespace std;
 8 
 9 typedef struct edge{
10     int to,next;
11     ll a,b,c,s;
12 }edge;
13 
14 edge e[MAX<<1];
15 int p[302],tot;
16 int n,m,st,ed;
17 ll dis[MAX];
18 
19 void dij(){
20     bool f[302]={0};
21     for(int i=1;i<=n;i++){
22         dis[i]=INF;
23     }
24     dis[st]=0;
25     for(int i=0;i<n;i++){
26         int u;
27         ll dd=INF;
28         for(int j=1;j<=n;j++){
29             if(!f[j] && dd>dis[j]) {
30                 dd=dis[j];
31                 u=j;
32             }
33         }
34         if(dd==INF) break;
35         f[u]=1;
36         for(int j=p[u];j!=-1;j=e[j].next){
37             ll t=dis[u];
38             ll r=t%e[j].s;
39             if(r>=e[j].a){
40                 t+=(e[j].s-r)+e[j].c;
41             }else{
42                 if(e[j].a-r>=e[j].c) t+=e[j].c;
43                 else t+=e[j].s-r+e[j].c;
44             }
45             dis[e[j].to]=min(t,dis[e[j].to]);
46         }
47     }
48 }
49 
50 inline void add(int u,int v,int a,int b,int c){
51     e[tot].to=v;    e[tot].next=p[u];
52     e[tot].a=a;     e[tot].b=b;     e[tot].c=c;     e[tot].s=a+b;
53     p[u]=tot++;
54 }
55 
56 int main()
57 {
58     int t,u,v,a,b,c;
59     //freopen("data.txt","r",stdin);
60     t=1;
61     while(scanf("%d %d %d %d",&n,&m,&st,&ed)!=EOF){
62         memset(p,-1,sizeof(p));
63         tot=0;
64         for(int i=0;i<m;i++){
65             scanf("%d %d %d %d %d",&u,&v,&a,&b,&c);
66             if(c<=a){
67                 add(u,v,a,b,c);
68                 //add(v,u,a,b,c);
69             }
70         }
71         dij();
72         printf("Case %d: %lld
",t++,dis[ed]);
73 
74     }
75     return 0;
76 }
/*12661*/

 

原文地址:https://www.cnblogs.com/sineatos/p/3910939.html