UVA 12661 Funny Car Racing

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值