#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 510;
const int INF = 0x3f3f3f3f;
int n, m, s, d;
int g[N][N]; //邻接矩阵存图
int dist[N]; // 起点到某点的最短距离
int p[N]; // 用于查找完整路径,p[i]表示节点i的上一个节点(父节点)
int help[N]; // 每个点救援队的数量
int cnt[N]; // 起点到某点的最短路径条数
int sum[N]; // 起点到某点的救援队总数量
bool st[N]; // 用于判断某个点是否被选过
void dijkstra() {
dist[s] = 0;
memset(p, -1, sizeof p);
sum[s] = help[s];
cnt[s] = 1;
for (int i = 0; i < n; i ++) {
int t = -1;
// 每次选择距离起点最近且没有被选过的点
for (int j = 0; j < n; j ++)
if (!st[j] && (t == -1 || dist[t] > dist[j]))
t = j;
for (int j = 0; j < n; j ++) {
// 此时更新最短距离,路径,救援队总数,最短路径数
if (dist[j] > dist[t] + g[t][j]) {
dist[j] = dist[t] + g[t][j];
p[j] = t;
sum[j] = sum[t] + help[j];
// 在最短路径中,到达节点j的路径只有一条时(即从t->j)
// 此时起点到j的最短路径数等于起点到t的最短路径数
cnt[j] = cnt[t];
}
// 此时更新路径,救援队总数,最短路径数
else if (dist[j] == dist[t] + g[t][j]) {
// 在最短路径中,当到达节点j的路径不止一条时
cnt[j] += cnt[t];
// 根据救援队总数来更新路径,保留总数最大的路径
if (sum[t] + help[j] > sum[j]) {
sum[j] = sum[t] + help[j];
p[j] = t;
}
}
}
st[t] = true;
}
}
// 路径输出
void findpath(int x) {
if (p[x] == -1) return;
findpath(p[x]);
printf("%d ", p[x]);
}
int main() {
memset(dist, 0x3f, sizeof dist);
memset(g, 0x3f, sizeof g);
cin >> n >> m >> s >> d;
for (int i = 0; i < n; i ++) cin >> help[i];
for (int i = 0; i < m; i ++) {
int a, b, c;
cin >> a >> b >> c;
g[a][b] = g[b][a] = c;
}
dijkstra();
printf("%d %d\n", cnt[d], sum[d]);
findpath(d);
printf("%d", d);
return 0;
}