Funny Car Racing - 最短路小技巧
Posted PushyTao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Funny Car Racing - 最短路小技巧相关的知识,希望对你有一定的参考价值。
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≤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. If it’s not possible to arrive at t from s (maybe your car is too slow!), print -1.
Samples
Input Copy
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
Output
Case 1: 20
Case 2: 9
题意:
n个路口,m条街道,每条街道都是有向的
并且这m条街道open a秒 close b秒(循环往复),自己的车通过这条道路需要t秒
可以从路口等待某一条道路open,必须在道路close 之前通过,且必须在另一条道路open的时候进入
问能否从s点到达t点,如果不能,输出-1,如果能输出最短的时间
细节的地方加在了代码里,在建图的过程中,如果说a > t,那么说这条路无论如何是走不过去的,所以干脆直接不建边
priority_queue<int, vector<int>, greater<int>> xiaogen;
priority_queue<int, vector<int>, less<int>> dagen;
const ll inf = 9223372036854775807;
const ll INF = 0x3f3f3f3f;
const int maxn = 3e5 + 7;
const int mod = 1000000007;
#define PI (double)acos(-1.0)
#define debug(x) cout << #x << " -> " << x << endl
#define ios \\
ios::sync_with_stdio(false); \\
cin.tie(NULL); \\
cout.tie(NULL);
#define lowbit(x) (x & (-x))
#define Clear(x, val) memset(x, val, sizeof x)
typedef pair<int, int> PII;
int cnt, head[maxn], n, m, s, t;
int dis[maxn], vis[maxn];
struct node {
int u, v, a, b, t;
int nex;
} e[maxn];
void add(int u, int v, int a, int b, int t) {
e[cnt].u = u, e[cnt].v = v;
e[cnt].a = a, e[cnt].b = b, e[cnt].t = t;
e[cnt].nex = head[u];
head[u] = cnt++;
}
void dij() {
priority_queue<PII> que;
Clear(dis, 0x3f3f3f3f);
Clear(vis, false);
dis[s] = 0;
que.push({0, s});
vis[s] = true;
while (que.size()) {
PII tp = que.top();
que.pop();
int u = tp.second;
vis[u] = false; /// not in the queue
for (int i = head[u]; ~i; i = e[i].nex) {
int v = e[i].v;
/**
t1代表到达该点时,道路已经开放多长时间,如果已经开放的时间 + 通过需要的时间 <= 该周期总共开放的时间
说明是可以通过的
否则就需要等待该门重新开放,总共时间 = 等待时间 + 通过时间
在该周期需要等待的时间 = a + b - t1
通过需要的时间即为t
所以总时间为 a + b - t1 + t
**/
int t1 = dis[u] % (e[i].a + e[i].b), t2;
if (t1 + e[i].t <= e[i].a)
t2 = e[i].t;
else
t2 = e[i].a + e[i].b + e[i].t - t1;
if (dis[v] > dis[u] + t2) {
dis[v] = dis[u] + t2;
if (!vis[v])
que.push({dis[v], v});
}
}
}
}
int main() {
int _ = 0;
while (cin >> n >> m >> s >> t) {
Clear(head, -1);
cnt = 0;
for (int i = 1; i <= m; i++) {
int u = read, v = read, a = read, b = read, t = read;
if (a < t)
continue;
add(u, v, a, b, t);
}
dij();
printf("Case %d: %d\\n", ++_, dis[t] == 0x3f3f3f3f ? -1 : dis[t]);
}
return 0;
}
/**
**/
以上是关于Funny Car Racing - 最短路小技巧的主要内容,如果未能解决你的问题,请参考以下文章
CSU 1333 & Uva 12661 Funny Car Racing最短路变形+spfa算法,链式前向星建图
[题解]UVa 12661 Funny Car Racing - spfa
UVa 12661 Funny Car Racing (dijkstra)