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 - 最短路小技巧的主要内容,如果未能解决你的问题,请参考以下文章

最短路 uva12661 Funny Car Racing

CSU 1333 & Uva 12661 Funny Car Racing最短路变形+spfa算法,链式前向星建图

[题解]UVa 12661 Funny Car Racing - spfa

UVa 12661 Funny Car Racing (dijkstra)

UVa 12661 - Funny Car Racing(Dijkstra)

UVA - 12661 Funny Car Racing (Dijkstra算法)