#include<bits/stdc++.h>
#define vi vector<int>
#define vvi vector<vector<int> >
using ll = long long;
using ld =long double;
#define int ll
#define INF 1e9
#define EPS 0.0000000001
#define rep(i,n) for(int i=0;i<n;i++)
#define loop(i,s,n) for(int i=s;i<n;i++)
#define all(in) in.begin(), in.end()
template<class T, class S> void cmin(T &a, const S &b) { if (a > b)a = b; }
template<class T, class S> void cmax(T &a, const S &b) { if (a < b)a = b; }
#define MAX 9999999
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
int W,H;
bool inrange(int x,int y){return (0<=x&&x<W)&&(0<=y&&y<H);}
using namespace std;
typedef pair<int, int> pii;
typedef pair<int,pii> piii;
#define MP make_pair
signed main(){
    int N,M,s,t;
    cin >> N >> M >> s >> t;
    --s,--t;
    vector<vector<pii>>graph(N);
    map<pii,int>mp;
    rep(i,M){
        int a,b,c,d; cin >> a >> b >> c >> d;
        --a,--b,--c;
        if(mp[pii(a,b)] == 0 || mp[pii(a,b)]>d)
            mp[pii(a,b)] = mp[pii(b,a)] = d;
        
        if(mp[pii(a,c)] == 0 || mp[pii(a,c)]>d)
            mp[pii(a,c)] = mp[pii(c,a)] = d;
        
        if(mp[pii(c,b)] == 0 || mp[pii(c,b)]>d)
            mp[pii(c,b)] = mp[pii(b,c)] = d;
    }
    for (auto itr :mp){
        graph[itr.first.first].push_back(pii(itr.first.second,itr.second));
    }
    //dijkstra
    priority_queue<pii,vector<pii>,greater<pii>>que;
    vector<int>d(N,INF*INF);
    d[s] = 0;
    pii _s = pii(0,s);
    que.push(_s);
    while(!que.empty()){
        pii temp = que.top();
        que.pop();
        int now = temp.first;
        int v = temp.second;
        if(now>d[v])continue;
        rep(i,graph[v].size()){
            int nd = now +graph[v][i].second;
            int next = graph[v][i].first;
            if(d[next] > nd){
                d[next] = nd;
                que.push(pii(nd,next));
            }
        }
    }
    cout << d[t] << endl;
}


