UVA 12661 Funny Car Racing
Time limit 1000 ms
Problem Description
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 ≤ 100,000), 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
Submit
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
#define INF 0x3f3f3f3f
#define maxn 400
struct node
{
int v, a, b, t;
} temp;
int N, M, S, T;
vector<node>n[maxn];
int visit[maxn], dist[maxn];
void add_road(int u, int v, int a, int b, int t)
{
if(a < t)//如果需要通过的时间大于路径开放时间就不能成功建路
return;
temp.v = v;
temp.a = a;
temp.b = b;
temp.t = t;
n[u].push_back(temp);
}
void spfa()
{
queue<int>q;
memset(visit, 0, sizeof(visit));
memset(dist, INF, sizeof(dist));
visit[S] = 1;
dist[S] = 0;
q.push(S);
while(!q.empty())
{
int p = q.front();
visit[p] = 0;
q.pop();
int s = n[p].size();
for(int i = 0; i < s; i++)
{
int to = n[p][i].v;//to为从p点能直接到达的点
int a = n[p][i].a;//to点开放时长
int b = n[p][i].b;//to点关闭时长
int t = n[p][i].t;//通过t耗时
if(dist[p] % (a+b) + t <= a)//此时to点时间状态+通过to点所需时间 <= to开放时间,则可以直接通过
{
if(dist[to] > dist[p] + t)//如果经过p点到to点比直接从起点到to点更快,更新dist
{
dist[to] = dist[p] + t;
if(!visit[to])//将被更新过得to点重新入队
{
visit[to] = 1;
q.push(to);
}
}
}
else//不能直接通过to点,意味着需要等待
{
if(dist[to] > dist[p] + a + b - dist[p]%(a+b) + t)//如果经过c点,且在to点多等待1轮(等to重新开放)比从起点到to点更快
{
dist[to] = dist[p] + a + b - dist[p]%(a+b) + t;//更新dist
if(!visit[to])//to入队
{
visit[to] = 1;
q.push(to);
}
}
}
}
}
}
int main()
{
int cases = 1;
while(~scanf("%d %d %d %d", &N, &M, &S, &T))
{
for(int i = 0; i <= N; i++)//初始化vector
n[i].clear();
for(int i = 0; i < M; i++)
{
int u, v, a, b, t;
scanf("%d %d %d %d %d", &u, &v, &a, &b, &t);
add_road(u, v, a, b, t);//建立单向路
}
spfa();
printf("Case %d: %d\n", cases++, dist[T]);
}
return 0;
}