#include <stdio.h>
#include <string.h>
#include<functional>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn = 2005;
const int inf = 1<<30;
int n,m,pos,Pos;
int Start,End;
struct node
{
int to,w,c,next;
}edge[maxn*20];
struct node1
{
int to,c,pos,next;
}Edge[maxn*20];
int Head[maxn],head[maxn],dis[maxn];
bool vis[maxn];
void addedge( int u,int v,int w,int c )
{
edge[++pos].to = v; edge[pos].w = w; edge[pos].c = c;
edge[pos].next = head[u]; head[u] = pos;
}
void addEdge( int u,int v,int c )
{
Edge[++Pos].to = v; Edge[Pos].c = c; Edge[Pos].pos = Pos;
Edge[Pos].next = Head[u]; Head[u] = Pos;
Edge[++Pos].to = u; Edge[Pos].c = 0; Edge[Pos].pos = Pos;
Edge[Pos].next = Head[u]; Head[u] = Pos;
}
vector<int>path[maxn];
typedef pair<int,int>pii;
void Dijstra( int s )
{
priority_queue<pii,vector<pii>,greater<pii> >que;
memset( vis,0,sizeof(vis) );
for( int i = 1; i <= n; i ++ )
dis[i] = inf;
dis[s] = 0;
que.push( make_pair(dis[s],s) );
while( !que.empty() )
{
pii u = que.top(); que.pop();
int v = u.second;
if( vis[v] ) continue;
vis[v] = 1;
for( int i = head[v]; i != -1; i = edge[i].next ){
node tmp = edge[i];
if( dis[tmp.to] > dis[v] + tmp.w ){
dis[tmp.to] = dis[v] + tmp.w;
que.push( make_pair( dis[tmp.to],tmp.to ) );
}
}
}
}
bool dinic_bfs( int start,int end )
{
memset(vis,0,sizeof(vis));
memset(dis,0,sizeof(dis));
vis[start] = true;
dis[start] = 0;
queue<int>q;
q.push(start);
while( !q.empty() )
{
int e = q.front();
q.pop();
if( e == end )
return true;
for( int i = Head[e]; i != -1; i = Edge[i].next )
{
if( !vis[ Edge[i].to] && Edge[i].c )
{
vis[ Edge[i].to] = true;
q.push( Edge[i].to );
dis[Edge[i].to] = dis[e] + 1;
}
}
}
return false;
}
int dinic_dfs( int start,int maxf,int end )
{
if( start==end )
return maxf;
int ans = 0,flow;
for( int i = Head[start]; i != -1; i = Edge[i].next )
{
if( dis[Edge[i].to] == dis[start] + 1 )
{
flow = dinic_dfs( Edge[i].to,Edge[i].c < maxf?Edge[i].c:maxf,end );
ans += flow;
maxf -= flow;
Edge[i].c -= flow;
Edge[Edge[i].pos^1].c +=flow;
if( maxf==0 )
break;
}
}
return ans;
}
int Dinic( int start,int end )
{
int ans = 0;
while( dinic_bfs( start,end ) )
ans += dinic_dfs( start, inf ,end );
return ans;
}
void dfs( int x )
{
vis[x] = 1;
for( int i = head[x]; i != -1; i = edge[i].next )
{
if( dis[edge[i].to] + edge[i].w == dis[x] ){
addEdge( x,edge[i].to,edge[i].c );
if( vis[edge[i].to] ) continue;
dfs( edge[i].to );
}
}
}
void Init()
{
pos = 0;Pos = 0;
for( int i = 0; i <= n; i ++ ){
head[i] = -1;
Head[i] = -1;
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("data.txt","r",stdin);
#endif
int cas = 1,x,y,w,c;
while( scanf("%d%d",&n,&m) != EOF,(n||m) )
{
Init();
scanf("%d%d",&Start,&End);
for( int i = 0; i < m; i ++ ){
scanf("%d%d%d%d",&x,&y,&w,&c);
addedge( x,y,w,c );
addedge( y,x,w,c );
}
Dijstra( Start );
memset( vis,0,sizeof(vis) );
dfs( End );
printf("Case %d: %d\n",cas ++,Dinic( End,Start ));
}
return 0;
}