#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <cstring>
#include <map>
#include <queue>
#include <cmath>
#include <complex> // complex<double> a(1.2 , 2.3);// real(): 1.2, imag()2.3
using namespace std;

#define MOD 1000000007
#define ll long long
#define ld long double
#define FOR(i,a,b) for(ll i=(ll)a;i<(ll)b;i++)
#define rep(i,n) FOR(i,0,n)
#define pb push_back
#define mp make_pair
#define all(a) a.begin(),a.end()
#define rall(a) a.rbegin(),a.rend()
#define rmsame(a) sort(all(a)),a.erase(unique(all(a)), a.end())
#define rmvector(a,b) rep(i,a.size())rep(j,b.size())if(a[i]==b[j]){a.erase(a.begin()+i);i--;break;}
#define first_more_idx(ve, num) upper_bound(all(ve), num)-ve.begin() // idx = first_more_idx(ve,num); if(idx = ve.size()) , then not exist
#define first_lessequal_idx(ve, num) lower_bound(all(ve), num)-ve.begin()
#define pq_pair_tB priority_queue <pair<ll,ll>, vector<pair<ll,ll> > , greater<pair<ll,ll> > >
#define pq_pair_ts priority_queue <pair<ll,ll> > // only sort first param
template<typename X> bool exist(vector<X> vec, X item){return find(all(vec), item)!=vec.end();}
ll gcd(ll a, ll b){if(b==0)return a;return gcd(b,a%b);}
ll lcm(ll a, ll b){return a/gcd(a,b)*b;}
ll power(ll x, ll n){if(n == 0) return 1;return  (n%2)? x*power(x, n-1)%MOD : power(x*x%MOD, n/2);}

//参考: https://github.com/kosakkun/procon_library/blob/master/graph/dijkstra.cpp
template <class T> struct Dijkstra {
    
    struct Edge{
        int to;
        T cost;
        Edge(int _to, T _cost) : to(_to), cost(_cost) {}
    };
    
    const T INF_ = numeric_limits<T>::max() / 2;
    vector< vector< Edge > > G;
    vector< T > d;
    Dijkstra (int n) : G(n), d(n) {}
    
    void add_directed_edge(int a, int b, T c) {
        G[a].push_back(Edge(b,c));
    }
    
    void add_undirected_edge(int a, int b, T c) {
        G[a].push_back(Edge(b,c));
        G[b].push_back(Edge(a,c));
    }
    
    void init(int s) {
        priority_queue< pair<T,int>,vector< pair<T,int> >, greater< pair<T,int> > > que;
        fill(d.begin(), d.end(), INF_);
        d[s] = 0;
        que.push(make_pair(0,s));
        while (!que.empty()){
            pair<T,int> p = que.top();
            que.pop();
            int v = p.second;
            if (d[v] < p.first) continue;
            for (int i = 0; i < G[v].size(); i++) {
                Edge e = G[v][i];
                if (d[e.to] > d[v] + e.cost) {
                    d[e.to] = d[v] + e.cost;
                    que.push(make_pair(d[e.to],e.to));
                }
            }
        }
    }
    
    T dist(int a) {
        return d[a];
    }
};
/*usage:
 O(N2): ノードの数の自乗
 初期化:
 Dijkstra<T> dj(N);// T: 経路の型, N: 点の数
 経路追加:
 dj.add_undirecter_edge(from, to , cost);
 dj.add_directer_edge(from, to , cost);
 計算:
 dj.init(root);//根元はrootから計算する
 cout << di.dist(N) << endl; // 点Nの最短距離を表示する。
 */


int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    ll N, M, S, T;
    cin >> N >> M >> S >> T;
    
    Dijkstra<ll> en(N);
    Dijkstra<ll> sunuku(N);
    
    S--; T--;
    rep(i, M){
        ll from , to, e, s;
        cin >> from >> to >> e >> s;
        
        from --;to --;
        
        en.add_undirected_edge(from, to, e);
        sunuku.add_undirected_edge(from, to, s);
    }
    
    en.init(S);
    sunuku.init(T);
    
    vector<ll> ans ;
    rep(i, N){
        ans.pb(en.dist(i) + sunuku.dist(i));
    }
    
    for(ll i = N-2; i >= 0; i--){
        ans[i] = min(ans[i], ans[i+1]);
    }
    
    rep(i, N){
        cout << ((ll)1e15)-ans[i] << endl;
    }
    
    //cout << fixed << setprecision(16) << ans << endl;
    return 0;
}


Measured memory_bytes: 19964