#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1000, INF = 2000000000;
struct edge {
  int x;
  int y;
  int w;
  int o;
};
vector<vector<edge> > G(MAXN + 1);
int n, m, depth[MAXN + 1], low[MAXN + 1], s, t, previous[MAXN + 1],
    prevCost[MAXN + 1], cntEdges[MAXN + 1][MAXN + 1], c, sons[MAXN + 1],
    p1 = -1, p2;
bool vis[MAXN + 1];
edge removedEdge = {0, 0, 0, -1}, e1, e2, prevEdge[MAXN + 1];
vector<edge> edgesOnPath, currentPath, allEdges;
bool eq(edge a, edge b) {
  return a.w == b.w && min(a.x, a.y) == min(b.x, b.y) &&
         max(a.x, a.y) == max(b.x, b.y);
}
void redo() {
  memset(prevCost, 0, sizeof(prevCost));
  memset(previous, 0, sizeof(previous));
  memset(vis, 0, sizeof(vis));
  memset(depth, 0, sizeof(depth));
  memset(low, 0, sizeof(low));
  memset(sons, 0, sizeof(sons));
  currentPath.clear();
}
bool isBridge(edge e) {
  if (cntEdges[e.x][e.y] == 1) {
    if (low[e.x] > depth[e.y] || low[e.y] > depth[e.x]) return true;
  } else {
    if (cntEdges[e.x][e.y] != 2) return false;
    if (min(removedEdge.x, removedEdge.y) != min(e.x, e.y) ||
        max(removedEdge.x, removedEdge.y) != max(e.x, e.y))
      return false;
    if (low[e.x] > depth[e.y] || low[e.y] > depth[e.x]) return true;
  }
  return false;
}
int getEdgeOrder(edge e) {
  for (int i = 0; i < allEdges.size(); i++)
    if (eq(e, allEdges[i]) == true && (i + 1 != p1)) return i + 1;
}
void dfs(int node) {
  vis[node] = true;
  for (int i = 0; i < G[node].size(); i++) {
    int nextNode = G[node][i].y;
    if (G[node][i].o != removedEdge.o) {
      if (vis[nextNode] == false) {
        sons[node]++;
        depth[nextNode] = depth[node] + 1;
        low[nextNode] = depth[nextNode];
        previous[nextNode] = node;
        prevCost[nextNode] = G[node][i].w;
        prevEdge[nextNode] = G[node][i];
        dfs(nextNode);
        low[node] = min(low[node], low[nextNode]);
      } else {
        if (previous[node] != nextNode)
          low[node] = min(low[node], low[nextNode]);
      }
    }
  }
}
void findPath(int x, int y, vector<edge> &e) {
  int node = t;
  while (node != x) {
    e.push_back(prevEdge[node]);
    node = previous[node];
  }
}
int answer = -1;
void solve() {
  if (m == 0) {
    cout << 0 << endl << 0;
    return;
  }
  dfs(s);
  if (vis[t] == false) {
    cout << 0 << endl << 0;
    return;
  }
  findPath(s, t, edgesOnPath);
  for (int i = 0; i < edgesOnPath.size(); i++)
    if (isBridge(edgesOnPath[i]) == true) {
      if (answer == -1 || answer > edgesOnPath[i].w) {
        answer = edgesOnPath[i].w;
        c = 1;
        e1 = edgesOnPath[i];
      }
    }
  for (int i = 0; i < edgesOnPath.size(); i++) {
    removedEdge = edgesOnPath[i];
    redo();
    dfs(s);
    if (vis[t] == true) findPath(s, t, currentPath);
    for (int j = 0; j < currentPath.size(); j++)
      if (isBridge(currentPath[j]) == true) {
        if (answer == -1 || removedEdge.w + currentPath[j].w < answer) {
          answer = removedEdge.w + currentPath[j].w;
          c = 2;
          e1 = removedEdge;
          e2 = currentPath[j];
        }
      }
  }
  cout << answer << endl;
  if (c != 0) cout << c << endl;
  if (c == 1) cout << e1.o;
  if (c == 2) {
    cout << e2.o << ' ' << e1.o;
  }
}
void readData() {
  scanf("%d %d %d %d", &n, &m, &s, &t);
  for (int i = 1; i <= m; i++) {
    int x, y, w;
    scanf("%d %d %d", &x, &y, &w);
    allEdges.push_back({min(x, y), max(x, y), w, i});
    if (x != y) {
      cntEdges[x][y]++;
      cntEdges[y][x]++;
      G[x].push_back({x, y, w, i});
      G[y].push_back({y, x, w, i});
      G[x][G[x].size() - 1].o = i;
      G[y][G[y].size() - 1].o = i;
    }
  }
}
int main() {
  readData();
  solve();
  return 0;
}
