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 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. 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
思路:用Dijkstra更新维护,每次找出最小的走。
学长的AC代码:
#include<algorithm>
#include<string.h>
#include<stdio.h>
#include<queue>
#include<math.h>
#define inf 0x3f3f3f3f
using namespace std;
const int N=303;
const int M=5e4+10;
int m,n,st,en,tot,head[N],dis[N];
bool vis[N];
struct node
{
    int v,dis,a,b,net;
} e[M];
void add(int aa,int bb,int cc,int dd,int ee)
{
    e[tot].v=bb;
    e[tot].dis=cc;
    e[tot].a=dd;
    e[tot].b=ee;
    e[tot].net=head[aa];
    head[aa]=tot++;
}
int dij()
{
    int time=0;
    memset(dis,0x3f,sizeof(dis));
    memset(vis,false,sizeof(vis));
    dis[st]=0;
    for(int i=1; i<=n; i++)
    {
        int u=-1,tmp=inf;
        for(int j=1; j<=n; j++)
        {
            if(!vis[j]&&dis[j]<tmp)
            {
                tmp=dis[j];
                u=j;
            }
        }
        if(u==-1) break;
        vis[u]=true;
        for(int j=head[u]; j!=-1; j=e[j].net)
        {
            int aa=e[j].a,bb=e[j].b,dist=e[j].dis;
            int t=dis[u]%(aa+bb);
            int v=e[j].v;
            if(aa<dist) co ntinue;
            if(aa-t>=dist&&dis[v]>dis[u]+dist)
            {
                dis[v]=dis[u]+dist;
                time+=dist;
            }
            else if(aa-t<dist&&dis[v]>dis[u]+dist+aa-t+bb)
            {
                dis[v]=dis[u]+dist+aa-t+bb;
            }
        }
    }
    return dis[en];
}
int main()
{
    int u,v,dis,aa,bb,k=1;
    while(~scanf("%d%d%d%d",&n,&m,&st,&en))
    {
        tot=0;
        memset(head,-1,sizeof(head));
        for(int i=0; i<m; i++)
        {
            scanf("%d%d%d%d%d",&u,&v,&aa,&bb,&dis);
            add(u,v,dis,aa,bb);
        }
        printf("Case %d: %d\n",k++,dij());
    }
}

我的wa代码:和上面代码一样思路。就是找不出错在哪!测试数据: https://blog.csdn.net/hurmishine/article/details/52318488
#include<algorithm>
#include<stdio.h>
#include<string.h>
#define M 50010
#define inf 0x3f3f3f
using namespace std;
int a[M][10];
int first[310],nextt[M];
int n,m;
int dis[310],vis[310];
int x,y,cas=1;
int dijskl(int x)
{
    memset(dis,0x3f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    dis[x]=0;
    int k,pan,flag,p,xian,an;
    for(int i=0; i<=n; i++)
    {
        pan=inf,k=-1;
        for(int j=0; j<=n; j++)
        {
            if(!vis[j]&&dis[j]<pan)
            {
                pan=dis[j];
                k=j;
            }
        }
        if(k==-1)
            break;
        vis[k]=1;
        p=first[k];
        while(p!=-1)
        {
            if(a[p][5]>a[p][3])
            {
                p=nextt[p];
                continue;
            }
            xian=dis[a[p][1]]%(a[p][3]+a[p][4]);
            if(a[p][3]-xian>=a[p][5])
            {
                an=a[p][5];
            }
            else
            {
                an=a[p][3]-xian+a[p][4]+a[p][5];
            }
            if(dis[a[p][2]]>dis[a[p][1]]+an)
            {
                dis[a[p][2]]=dis[a[p][1]]+an;
            }
//            if(a[p][3]-xian>=a[p][5]&&dis[a[p][2]]>dis[a[p][1]]+a[p][5])
//            {
//                dis[a[p][2]]=dis[a[p][1]]+a[p][5];
//            }
//            else if(a[p][3]-xian<a[p][5]&&dis[a[p][2]]>dis[a[p][1]]+a[p][5]+a[p][3]-xian+a[p][4])
//            {
//                dis[a[p][2]]=dis[a[p][1]]+a[p][5]+a[p][3]-xian+a[p][4];
//            }
            p=nextt[p];
        }
    }
    return dis[y];
}
int main()
{
    while(~scanf("%d%d%d%d",&n,&m,&x,&y))
    {
        memset(first,-1,sizeof(first));
        for(int i=1; i<=m; i++)
        {
            scanf("%d%d%d%d%d",&a[i][1],&a[i][2],&a[i][3],&a[i][4],&a[i][5]);
            nextt[i]=first[a[i][1]];
            first[a[i][1]]=i;
        }
//        dijskl(x);
        printf("Case %d: %d\n",cas++,dijskl(x));
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值