题目大意:有几条路,每条路会周期性关闭,题目给出了每条路的起点和终点,以及这条路会打开a秒,关闭b秒,通过这条需要的时间t,比赛开始时道路都刚刚打开,求到终点最少时间
解题思路:用dijkstra求最短路,每个点记录一下到达该点时经过的时间,中间判断下当前时间是否需要等待道路开放即可
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#define maxn 1000
#define INF 0x3f3f3f3f
using namespace std;
struct Node {
int t, p;
bool operator < (const Node& rhs) const {
return t>rhs.t;
}
};
struct Edge {
int from;
int to;
int open;
int close;
int pass;
Edge(int from, int to, int open, int close, int pass):from(from), to(to), open(open), close(close), pass(pass){}
};
int n, m;
vector<Edge> edges;
vector<int> G[maxn];
void addEdge(int from, int to, int open, int close, int pass) {
edges.push_back(Edge(from, to, open, close, pass));
int i = edges.size();
G[from].push_back(i-1);
}
long long int Dij(int s, int t) {
int visit[maxn];
long long int dij[maxn];
for(int i = 0; i < maxn; i++) {
dij[i] = INF;
}
dij[s] = 0;
memset(visit, 0, sizeof(visit));
priority_queue<Node> que;
que.push((Node){0, s});
while(!que.empty()) {
Node po = que.top();
que.pop();
if(visit[po.p])
continue;
visit[po.p] = 1;
for(int i = 0; i < G[po.p].size(); i++) {
Edge& ed = edges[G[po.p][i]];
if(ed.pass > ed.open)
continue;
int l = po.t % (ed.open + ed.close);
int lt;
if(ed.open - l >= ed.pass)
lt = ed.pass;
else {
lt = ed.pass + ed.open + ed.close - l;
}
if(dij[ed.to] > dij[po.p] + lt) {
dij[ed.to] = dij[po.p] + (long long int)lt;
que.push((Node){dij[ed.to], ed.to});
}
}
}
return dij[t];
}
int main() {
int cou = 0;
int s, t;
while(cin >> n >> m >> s >> t && n && m) {
edges.clear();
cou++;
for(int i = 0; i <= n; i++)
G[i].clear();
int a, b, c, d, e;
while(m--) {
cin >> a >> b >> c >> d >> e;
addEdge(a, b, c, d, e);
}
cout << "Case "<< cou << ": " <<Dij(s, t) << endl;
}
return 0;
}