Problem : Funny Car Racing
Description : 有n个城市,m条边,问你从城市s到tt的总时间。每条路都有开放时间和关闭时间,还给出了你通过那条路的时间,你必须在那条路开放的时间内通过那条路,不然的话就只能等待那条再次开放然后通过,开关的计时是在从城市s出发开始的。
Solution : 最短路径的变形,改一下松弛条件就可以了。需要注意的是这题的输入不能用cin,我表示再也不入C++输入的坑了。
Code (C++) :
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#define N 400
#define M 50050
#define inf 0x3f3f3f3f
using namespace std;
int visit[N],n,t;
int dis[N];
int head[N];
struct edge
{
int u;
int v;
int cost;
int open;
int close;
int next;
} e[M];
void addedge(int u,int v,int open,int close,int c)
{
e[t].u=u;
e[t].v=v;
e[t].open=open;
e[t].close=close;
e[t].cost=c;
e[t].next=head[u];
head[u]=t++;
}
void Spfa(int src)
{
int u,v,weight,sum;
int rest,total,re,ce;
memset(visit,0,sizeof(visit));
memset(dis,inf,sizeof(dis));
dis[src]=0;
queue<int>q;
while(!q.empty())
q.pop();
q.push(src);
visit[src]=1;
while(!q.empty())
{
u=q.front();
q.pop();
visit[u]=0;
sum=dis[u];
for(int i=head[u]; i!=-1; i=e[i].next)
{
if(e[i].cost>e[i].open)
continue;
v=e[i].v;
weight=e[i].cost;
total=e[i].open+e[i].close;
rest=sum%total;
//如果我到达那个点时门已经关了,那么我就需要等待剩余的关门时间,还有通过那条路的时间
if(rest>=e[i].open)
{
ce=rest-e[i].open;
if(ce==0&&dis[v]>dis[u]+weight+e[i].close)
{
dis[v]=dis[u]+weight+e[i].close;
if(!visit[v])
{
q.push(v);
visit[v]=1;
}
}
else if(ce>0&&dis[v]>dis[u]+e[i].close-ce+weight)
{
dis[v]=dis[u]+weight+e[i].close-ce;
if(!visit[v])
{
q.push(v);
visit[v]=1;
}
}
}
//如果我到达那个点时门还开着,这时候就需要判断了
else
{
re=e[i].open-rest;
//如果门剩余开着的时间大于我通过那条路的时间,那么我就可以直接通过
if(weight<=re&&dis[v]>dis[u]+weight)
{
dis[v]=dis[u]+weight;
if(!visit[v])
{
q.push(v);
visit[v]=1;
}
}
//如果门开着的剩余时间不够我通过那条路,这时候我就需要等待门剩余开着的时间,门关着的时间,还有我通过那条路的时间
else if(weight>re&&dis[v]>dis[u]+e[i].close+weight+re)
{
dis[v]=dis[u]+weight+re+e[i].close;
if(!visit[v])
{
q.push(v);
visit[v]=1;
}
}
}
}
}
}
int main()
{
//freopen ("in.txt","r",stdin);
int m,s,u,v,tt,open,close,th,k=1;
while(~scanf("%d%d%d%d",&n,&m,&s,&tt))
{
t=0;
memset(head,-1,sizeof(head));
for(int i=0; i<m; i++)
{
scanf("%d%d%d%d%d",&u,&v,&open,&close,&th);
//cin>>u>>v>>open>>close>>th;
addedge(u,v,open,close,th);
}
Spfa(s);
int ans=dis[tt];
cout<<"Case "<<k++<<": "<<ans<<endl;
}
return 0;
}