#include <iostream>
#include <vector>
#include <utility>
#include <cstring>
#include <algorithm>
#include <map>
#include <queue>
#include <stack>
#include <cstdio>
#include <set>
#define
using namespace std;
typedef long long ll;
#define
#define
typedef pair<int, int> P;
struct Edge
{
int first;
int open;
int close;
int second;
bool operator < (const Edge& t)const {
return t.second < this->second;
}
};
vector<Edge>vec[MAXN];
priority_queue<Edge, vector<Edge> >que;
ll dis[MAXN];
bool vis[MAXN];
ll N, M, START, END;
void Dijkstra(int start) {
dis[start] = 0;
que.push({ start,0,0,0 });
while (!que.empty()) {
Edge tmp = que.top();
que.pop();
if (vis[tmp.first] == true) {
continue;
}
vis[tmp.first] = true;
for (int i = 0; i < vec[tmp.first].size(); i++) {
ll pos = vec[tmp.first][i].first;
ll val = vec[tmp.first][i].second;
ll open = vec[tmp.first][i].open;
ll close = vec[tmp.first][i].close;
ll time = dis[tmp.first] % (open + close);
if (time >= open) {
dis[pos] = min(dis[tmp.first] + (close - (time - open)) + val, dis[pos]);
if (!vis[pos])
que.push({ pos,open,close,dis[pos] });
}
else {
if (open - time >= val) {
dis[pos] = min(dis[tmp.first] + val, dis[pos]);
if (!vis[pos])
que.push({ pos,open,close,dis[pos] });
}
else {
dis[pos] = min(dis[tmp.first] + val + (open + close) - time, dis[pos]);
if (!vis[pos])
que.push({ pos,open,close,dis[pos] });
}
}
}
}
}
int main() {
ios;
ll T = 0;
while (cin>> N >> M >> START >> END) {
fill(dis, dis + N + 1, INT_MAX);
memset(vis, false, sizeof(vis));
for (vector<Edge>& t : vec) {
t.clear();
}
for (int i = 0; i < M; i++) {
ll a, b, c, d, e;
cin >> a >> b >> c >> d >> e;
if (c < e)
continue;
vec[a].push_back({ b,c,d,e });
}
Dijkstra(START);
cout << "Case " << ++T << ": ";
cout << dis[::END] << endl;
}
return 0;
}