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 }
代码君

 

你可能感兴趣的:(最短路)