#include <iostream>
#include <array>
#include <algorithm>
#include <vector>
#include <bitset>
#include <set>
#include <unordered_set>
#include <cmath>
#include <complex>
#include <deque>
#include <iterator>
#include <numeric>
#include <map>
#include <unordered_map>
#include <queue>
#include <stack>
#include <string>
#include <tuple>
#include <utility>
#include <limits>
#include <iomanip>
#include <functional>
#include <cassert>
using namespace std;

using ll=long long;
template<class T> using V = vector<T>;
template<class T, class U> using P = pair<T, U>;
using vll = V<ll>;
using vvll = V<vll>;
#define rep(i, k, n) for (ll i=k; i<(ll)n; ++i)
#define REP(i, n) rep(i, 0, n)
#define ALL(v) v.begin(),v.end()
template < class T > inline bool chmax(T& a, T b) {if (a < b) { a=b; return true; } return false; }
template < class T > inline bool chmin(T& a, T b) {if (a > b) { a=b; return true; } return false; }
#define DEBUG_VLL(vec) REP(sz, vec.size()) std::cerr<<vec[sz]<<(sz==vec.size()-1?'\n':' ');

const long long MOD = 1000000007;
const long long HIGHINF = (long long)1e18;
const int INF = (int)1e9;

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    ll n, m, s, t; cin >> n >> m >> s >> t;
    s--, t--;
    V< V< P<ll, ll> > > yen_graph(n), snuuk_graph(n);
    for (ll i = 0; i < m; i++) {
        ll u, v, a, b; cin >> u >> v >> a >> b;
        u--, v--;
        yen_graph[u].emplace_back( make_pair(v, a) );
        yen_graph[v].emplace_back( make_pair(u, a) );
        snuuk_graph[u].emplace_back( make_pair(v, b) );
        snuuk_graph[v].emplace_back( make_pair(u, b) );
    }

    vll yen_dist(n, HIGHINF), snuuk_dist(n, HIGHINF);
    // {距離, 頂点} を格納しておく優先度付きキュー（距離の小さい順に取り出す）
    priority_queue< P<ll, ll>, V< P<ll, ll> >, greater< P<ll, ll> > > pq;
    // 円のスタートは s なので、{0, s} を格納しておく
    pq.push( make_pair(0, s) );
    while (!pq.empty()) {
        // 最短距離から順に取り出して更新
        P<ll, ll> q = pq.top();
        pq.pop();
        // もし最短距離が求まっているならパス
        if (yen_dist[q.second] < HIGHINF) continue;
        // 最短距離を更新
        yen_dist[q.second] = q.first;
        for (P<ll, ll> nxt: yen_graph[q.second]) {
            if (yen_dist[nxt.first] == HIGHINF) {
                // まだ最短距離が更新されていないなら候補を突っ込む
                pq.push( make_pair(yen_dist[q.second] + nxt.second, nxt.first) );
            }
        }
    }

    // スヌークのスタートは t なので、{0, t} を格納しておく
    pq.push( make_pair(0, t) );
    while (!pq.empty()) {
        // 最短距離から順に取り出して更新
        P<ll, ll> q = pq.top();
        pq.pop();
        // もし最短距離が求まっているならパス
        if (snuuk_dist[q.second] < HIGHINF) continue;
        // 最短距離を更新
        snuuk_dist[q.second] = q.first;
        for (P<ll, ll> nxt: snuuk_graph[q.second]) {
            if (snuuk_dist[nxt.first] == HIGHINF) {
                // まだ最短距離が更新されていないなら候補を突っ込む
                pq.push( make_pair(snuuk_dist[q.second] + nxt.second, nxt.first) );
            }
        }
    }

    // かかるお金の最小値
    ll tmp = HIGHINF;
    vll ans(n);
    // 後ろから見ていくことで
    // 頂点 n だけ使える時
    // 頂点 n, n - 1 が使える時
    // ……
    // を随時更新していく
    for (ll i = n - 1; i >= 0; i--) {
        chmin(tmp, yen_dist[i] + snuuk_dist[i]);
        ans[i] = (ll)1e15 - tmp;
    }

    for (ll i = 0; i < n; i++) cout << ans[i] << '\n';
    return 0;
}


Measured memory_bytes: 19576