UvA 12661 Funny Car Racing (最短路)

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 rst 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 ve 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. 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

题意:一个有向图,有M条路,每条路从u到v,并且,这条路每次开通a个单位时间,然后关闭b个单位时间,再开通a个单位时间......通过这条路的时间是t个单位时间,求起点s到终点t的最短时间

分析:最短路,只是说,在松弛的时候要注意

1、这条路如果通过的时间 t>a 的话,则这条路是不能通过的

2、如果到达下一个点剩下的时间 res<t  的话,还要算上等待的时间,这就相当于,延长的通过的时间。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<string>
#include<iostream>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<map>
#include<stdlib.h>
#include<algorithm>
#define LL __int64
#define FIN freopen("in.txt","r",stdin)
using namespace std;
const int MAXN=300+5;
const int INF=0x3f3f3f3f;
int n,m,s,t;
struct EDGE
{
    int v,t,a,b;
    EDGE(int a,int b,int c,int d): v(a),a(b),b(c),t(d){ }
};
vector<int> G[MAXN];
vector<EDGE> edge;
int d[MAXN];
int inq[MAXN];

void spfa()
{
    for(int i=0;i<=n;i++) d[i]=INF;
    d[s]=0;
    memset(inq,0,sizeof(inq));
    queue<int> Q;
    Q.push(s);
    inq[s]=1;
    while(!Q.empty())
    {
        int u=Q.front();Q.pop();
        inq[u]=0;
        for(int i=0;i<G[u].size();i++)
        {
            EDGE tmp=edge[G[u][i]];
            int v=tmp.v,a=tmp.a,b=tmp.b,t=tmp.t;
            if(t>a) continue;
            int res=d[u]%(a+b);
            if(res+t<=a)
            {
                if(d[u]+t<d[v])
                {
                    d[v]=d[u]+t;
                    if(!inq[v]) {Q.push(v);inq[v]=1;}
                }
            }
            else
            {
                int num=d[u]+(a+b)-res+t;
                if(num<d[v])
                {
                    d[v]=num;
                    if(!inq[v]) {Q.push(v);inq[v]=1;}
                }
            }
        }
    }
}
int main()
{
    int Case=0;
    while(scanf("%d %d %d %d",&n,&m,&s,&t)!=EOF)
    {
        int tot=0;
        edge.clear();
        for(int i=0;i<=n;i++) G[i].clear();
        while(m--)
        {
            int u,v,a,b,t;
            scanf("%d %d %d %d %d",&u,&v,&a,&b,&t);
            edge.push_back(EDGE(v,a,b,t));
            G[u].push_back(tot++);
        }
        spfa();
        printf("Case %d: %d\n",++Case,d[t]);
    }
    return 0;
}
View Code

 

posted @ 2015-08-18 17:02  Cliff Chen  阅读(197)  评论(0编辑  收藏  举报