大意:在一个赛车比赛中,赛道有n个交叉点和m条单项道路,每条路都是周期性关闭的。每条路用5个整数u, v, a, b, t表示,表示起点是u,终点是v,通过时间是t,另外,这条路会打开a秒,然后关闭b秒,周期循环。当比赛开始时,这条道路刚刚打开。你的赛车必须在道路打开的时候进入该道路,并且这它关闭之前离开。现在求给定起点s到终点t的最短时间。
思路:虽然路径的权值变成了动态变化的,但依旧符合Dijkstra算法的贪心思想,照样搞。
// Created by Chenhongwei in 2015.
// Copyright (c) 2015 Chenhongwei. All rights reserved.
#include"iostream"
#include"cstdio"
#include"cstdlib"
#include"cstring"
#include"climits"
#include"queue"
#include"cmath"
#include"map"
#include"set"
#include"stack"
#include"vector"
#include"sstream"
#include"algorithm"
using namespace std;
typedef long long ll;
const int maxn=500;
struct Edge
{
int to,dis,a,b;
Edge(int to,int dis,int a,int b):to(to),dis(dis),a(a),b(b) {}
};
vector<Edge> g[maxn];
int n,m,s,t,kase,d[maxn];
bool f[maxn];
void spfa()
{
memset(d,0x3f,sizeof d);
d[s]=0;
memset(f,0,sizeof f);
queue<int > q;
q.push(s),f[s]=1;
while(!q.empty())
{
int u=q.front();
q.pop();
f[u]=0;
for(int i=0;i<g[u].size();i++)
{
Edge e=g[u][i];
int v=e.to,w=e.dis,a=e.a,b=e.b;
if(w>a)continue;
int now=d[u]%(a+b);
if(a-now>=w)
{
if(d[v]>d[u]+w)
{
d[v]=d[u]+w;
if(!f[v])
q.push(v);
}
}
else
{
if(d[v]>d[u]+w+a+b-now)
{
d[v]=d[u]+w+a+b-now;
if(!f[v])
q.push(v);
}
}
}
}
}
int main()
{
//ios::sync_with_stdio(false);
// freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int kase=0;
while(~scanf("%d%d%d%d",&n,&m,&s,&t))
{
for(int i=0;i<=n;i++)
g[i].clear();
int id=0;
for(int i=1;i<=m;i++)
{
int u,v,a,b,d;
scanf("%d%d%d%d%d",&u,&v,&a,&b,&d);
g[u].push_back(Edge(v,d,a,b));
}
spfa();
printf("Case %d: %d\n",++kase,d[t]);
}
return 0;
}