UVa 12661 (单源最短路) Funny Car Racing

题意:

有一个赛车跑道,可以看做一个加权有向图。每个跑道(有向边)还有一个特点就是,会周期性地打开a秒,然后关闭b秒。只有在赛车进入一直到出来,该跑道一直处于打开状态,赛车才能通过。

开始时所有跑道处于刚打开的状态,求从起点到终点的最短时间。

分析:

设d[i]为起点到节点i的最短时间。

和普通的单源最短路问题一样,只不过在进行松弛操作的时候分两种情况。松弛的前提是,赛道打开的时间不短于赛车通过的时间。

  1. 赛车从进入直到出跑道,一直是打开状态。则d[v] = min(d[v], d[u] + t)
  2. 赛道已经关闭或会在中途关闭,则只能等到下次刚刚打开时进入,因此有个等待时间。d[v] = min(d[v], d[u] + wait + t)
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn = 300 + 10;
 5 const int INF = 1000000000;
 6 
 7 struct Edge
 8 {
 9     int from, to, a, b, t;
10     Edge(int u, int v, int a, int b, int t):from(u), to(v), a(a), b(b), t(t) {}
11 };
12 
13 vector<Edge> edges;
14 vector<int> G[maxn];
15 bool inq[maxn];
16 int n, m, s, t, d[maxn];
17 
18 void Init()
19 {
20     edges.clear();
21     for(int i = 0; i < n; ++i) G[i].clear();
22 }
23 
24 void AddEdge(int u, int v, int a, int b, int t)
25 {
26     edges.push_back(Edge(u, v, a, b, t));
27     int m = edges.size();
28     G[u].push_back(m-1);
29 }
30 
31 void SPFA()
32 {
33     memset(inq, false, sizeof(inq));
34     for(int i = 0; i < n; ++i) d[i] = INF;
35     queue<int> Q;
36     d[s] = 0; inq[s] = true; Q.push(s);
37 
38     while(!Q.empty())
39     {
40         int u = Q.front(); Q.pop();
41         inq[u] = false;
42         for(int i = 0; i < G[u].size(); ++i)
43         {
44             Edge& e = edges[G[u][i]];
45             int v = e.to, a = e.a, b = e.b, t = e.t;
46             if(a < t) continue;
47             int now = d[u] % (a+b);
48             if(now + t <= a)
49             {//情况一
50                 if(d[v] > d[u] + t)
51                 {
52                     d[v] = d[u] + t;
53                     Q.push(v);
54                     inq[v] = true;
55                 }
56             }
57             else
58             {//情况二
59                 int wait = a + b - now;
60                 if(d[v] > d[u] + wait + t)
61                 {
62                     d[v] = d[u] + wait + t;
63                     Q.push(v);
64                     inq[v] = true;
65                 }
66             }
67         }
68     }
69 }
70 
71 int main()
72 {
73     //freopen("in.txt", "r", stdin);
74 
75     int kase = 0;
76     while(scanf("%d%d%d%d", &n, &m, &s, &t) == 4)
77     {
78         s--; t--;
79         Init();
80         for(int i = 0; i < m; ++i)
81         {
82             int u, v, a, b, t;
83             scanf("%d%d%d%d%d", &u, &v, &a, &b, &t);
84             AddEdge(u-1, v-1, a, b, t);
85         }
86         SPFA();
87         printf("Case %d: %d\n", ++kase, d[t]);
88     }
89 
90     return 0;
91 }
代码君

 

posted @ 2015-02-14 20:25  AOQNRMGYXLMV  阅读(410)  评论(0编辑  收藏  举报