#include<cmath>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<stack>
#include<vector>
#include<queue>
#include<string>
#include<map>
using namespace std;

//90min
//耗时于程序编写、改bug

/*************************
题意:给出1个图,每条边有对应的距离d和时间t。
①求一条“距离最短路”,若有多条,则选时间最短的。
②再求一条“时间最短路”,若有多条,则选节点最少的。
③并输出两条路的所经节点,若两条路相同,一起输出。
*************************/


/************************
求解要点:根据N=500,直接用dijkstra不会超时。
★双条件问题,只需要在判断区域修改条件,增加一点“若距离相等,选取时间最短”
另一条路同理,为了节省时间和错误率,直接复制函数修改。注意更新权值时,要更新2个值。
★输出所经节点用pre[i],每次更新某点权值,修改其pre。
************************/

/***********************
笔记:
①dijktra题中,INF即最大整数值不可取7ffffff
因为有一个d[]+dis[]<dis[]的判断过程,若把dis取整数最大,会溢出。
②注意判断输入中节点序号是从0开始,还是从1开始!自己写测试用例时也要注意。
③注意当找不到新的最短路需要退出时,若有其他后续操作,应执行break而不是return
④当发现找不到bug时,火速进行断点或日志定位bug位置,不要在那发呆
*********************/


#define INF 0xfffffff //int32位,去除首位符号位,最大为该值
#define M 600
int dis[M][M];
int Time[M][M];
int n,m;

int End,start;
int vis[M];
int dismin,Timemin;
vector<int> ansTime,ansdis;
void dj_dis()
{
int i,j,select;
int dmin,tmin;
memset(vis,0,sizeof(vis));
int d[M],t[M],pre[M];

for(i=0;i<n;i++)
{
d[i]=INF;
t[i]=INF;
}

d[start]=0;
t[start]=0;
pre[start]=-1;

for(i=0;i<n;i++)
{
dmin=INF;
tmin=INF;
for(j=0;j<n;j++)
{
if(vis[j]==0 && (d[j]<dmin || (d[j]==dmin && t[j]<tmin)))
{
dmin=d[j];
tmin=t[j];
select=j;
}
}
if(dmin==INF)
break;//找不到了

vis[select]=1;
for(j=0;j<n;j++)
{
if(vis[j]==1)
continue;

if(d[select]+dis[select][j]<d[j] )
{
d[j] = d[select]+dis[select][j];
t[j] = t[select]+Time[select][j];
pre[j]=select;

}
else if(d[select]+ dis[select][j] == d[j] && t[select] + Time[select][j] < t[j])
{
t[j] = t[select] + Time[select][j];
pre[j]=select;

}
}
}
int p=End;
while(p!=-1)
{
ansdis.push_back(p);
p=pre[p];
}

dismin=d[End];
}

void dj_Time()
{
int i,j,select;
int dmin,tmin;
memset(vis,0,sizeof(vis));
int d[M],t[M],pre[M],node[M];

for(i=0;i<n;i++)
{
node[M]=INF;
t[i]=INF;
}

t[start]=0;
node[start]=1;
pre[start]=-1;

int nodemin;
for(i=0;i<n;i++)
{
nodemin=INF;
tmin=INF;
for(j=0;j<n;j++)
{
if(vis[j]==0 && (t[j]<tmin || (t[j]==tmin && node[j]<nodemin)))
{
nodemin=node[j];
tmin=t[j];
select=j;
}
}
// cout<<"select="<<select<<Endl;
if(tmin==INF)
break;//找不到了

vis[select]=1;
for(j=0;j<n;j++)
{
if(vis[j]==1)
continue;

if(t[select]+Time[select][j]<t[j] )
{
t[j] = t[select]+Time[select][j];
pre[j]=select;
node[j]=node[select]+1;
// printf("select=%d,j=%d\n",select,j);
}
else if(t[select]+ Time[select][j] == t[j] && node[select] + 1 < node[j])
{
node[j]=node[select]+1;
pre[j]=select;
// printf("select=%d,j=%d\n",select,j);
}
}
}
// cout<<"p1"<<Endl;
int p=End;

while(p!=-1)
{
ansTime.push_back(p);
p=pre[p];
}

Timemin=t[End];

}
int main()
{
int i,j;
int s,e,w,l,t;
scanf("%d%d",&n,&m);

for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
if(i==j)
dis[i][j]=Time[i][j]=0;
else
dis[i][j]=dis[j][i]=Time[i][j]=Time[j][i]=INF;
}


for(i=0;i<m;i++)
{
scanf("%d%d%d%d%d",&s,&e,&w,&l,&t);
if(w==1)
{
dis[s][e]=l;
Time[s][e]=t;
}
else
{
dis[s][e]=dis[e][s]=l;
Time[s][e]=Time[e][s]=t;
}

}
scanf("%d%d",&start,&End);
dj_dis();
dj_Time();


int samef=1;
if(ansTime.size()!=ansdis.size())
samef=0;
else
for(i=0;i<ansTime.size();i++)
if(ansTime[i]!=ansdis[i])
{
samef=0;
}

if(samef==0)
{
printf("Distance = %d:",dismin);
for(i=ansdis.size()-1;i>=0;i--)
{
printf(" %d",ansdis[i]);
if(i>0)
cout<<" ->";
else cout<<endl;
}

printf("Time = %d:",Timemin);
for(i=ansTime.size()-1;i>=0;i--)
{
printf(" %d",ansTime[i]);
if(i>0)
cout<<" ->";
else cout<<endl;
}
}
else
{
printf("Distance = %d; ",dismin);

printf("Time = %d:",Timemin);
for(i=ansTime.size()-1;i>=0;i--)
{
printf(" %d",ansTime[i]);
if(i>0)
cout<<" ->";
else cout<<endl;
}
}
return 0;
}