#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;   }