#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
constexpr int Inf = 1000000010;
constexpr ll INF= 1000000000000000000;
constexpr ll MOD = 1000000007;
const double PI = 3.1415926535897;
typedef pair<ll,ll> P;

template<typename T>
T Pow(T a,T b) {
    T ret = 1;
    for(int i = 0;i < b;i++) {
        ret *= a;
    }
    return ret;
}

ll mod(ll val) {
    ll res = val % MOD;
    if(res < 0) {
        res += MOD;
    }
    return res;
}

ll RS(ll N, ll P, ll M){
    if(P==0) return 1;
    if(P < 0) {
        return 0;
    }
    if(P%2==0){
        ll t = RS(N, P/2, M);
        return t*t % M;
    }
    return N * RS(N, P-1, M) % M;
}

ll digit(ll a) {
    ll ret = 0;
    while(a > 0) {
        ret += a % 10;
        a /= 10;
    }
    return ret;
}

struct edge{
	int to;
    ll cost;
};

int V; //頂点数
vector<edge> G1[100010];
vector<edge> G2[100010];
ll d1[100010]; //頂点sからの最短距離
ll d2[100010];
int pre[100010];

void dijkstra1(int s) {
	//greater<P>を指定することでfirstが小さい順に取り出せる
	priority_queue<P,vector<P>,greater<P>> que;
	fill(d1,d1 + V,INF);
	fill(pre,pre + V,-1);
	d1[s] = 0;
	que.push(P(0,s));

	while(!que.empty()) {
		P p = que.top();
		que.pop();
		int v = p.second;
		if(d1[v] < p.first) {
			continue;
		}
		for(int i = 0;i < G1[v].size();i++) {
			edge e = G1[v][i];
			if(d1[e.to] > d1[v] + e.cost) {
				d1[e.to] = d1[v] + e.cost;
				pre[e.to] = v;
				que.push(P(d1[e.to],e.to));
			}
		}
	}
}

void dijkstra2(int s) {
	//greater<P>を指定することでfirstが小さい順に取り出せる
	priority_queue<P,vector<P>,greater<P>> que;
	fill(d2,d2 + V,INF);
	fill(pre,pre + V,-1);
	d2[s] = 0;
	que.push(P(0,s));

	while(!que.empty()) {
		P p = que.top();
		que.pop();
		int v = p.second;
		if(d2[v] < p.first) {
			continue;
		}
		for(int i = 0;i < G2[v].size();i++) {
			edge e = G2[v][i];
			if(d2[e.to] > d2[v] + e.cost) {
				d2[e.to] = d2[v] + e.cost;
				pre[e.to] = v;
				que.push(P(d2[e.to],e.to));
			}
		}
	}
}

//抽象化セグ木。基本的には普通のセグ木でいいが、乗せるものがintじゃない（例えば1次方程式とか）に使える
template <class T>
class SegTree {
    int n;                       // 葉の数
    vector<T> data;              // データを格納するvector
    T def;                       // 初期値かつ単位元
    function<T(T, T)> operation; // 区間クエリで使う処理
    function<T(T, T)> update;    // 点更新で使う処理

    // 区間[a,b)の総和。ノードk=[l,r)に着目している。
    T _query(int a, int b, int k, int l, int r) {
        if (r <= a || b <= l) return def; // 交差しない
        if (a <= l && r <= b)
            return data[k]; // a,l,r,bの順で完全に含まれる
        else {
            T c1 = _query(a, b, 2 * k + 1, l, (l + r) / 2); // 左の子
            T c2 = _query(a, b, 2 * k + 2, (l + r) / 2, r); // 右の子
            return operation(c1, c2);
        }
    }

  public:
    // _n:必要サイズ, _def:初期値かつ単位元, _operation:クエリ関数,
    // _update:更新関数
    SegTree(size_t _n, T _def, function<T(T, T)> _operation,
            function<T(T, T)> _update)
        : def(_def), operation(_operation), update(_update) {
        n = 1;
        while (n < _n) {
            n *= 2;
        }
        data = vector<T>(2 * n - 1, def);
    }

    // 場所i(0-indexed)の値をxで更新
    void change(int i, T x) {
        i += n - 1;
        data[i] = update(data[i], x);
        while (i > 0) {
            i = (i - 1) / 2;
            data[i] = operation(data[i * 2 + 1], data[i * 2 + 2]);
        }
    }

    // [a, b)の区間クエリを実行
    T query(int a, int b) {
        return _query(a, b, 0, 0, n);
    }

    // 添字でアクセス
    T operator[](int i) {
        return data[i + n - 1];
    }
};

int main() {
    cin >> V;
    int M;
    cin >> M;
    int s,t;
    cin >> s >> t;
    s--;
    t--;
    for(int i = 0;i < M;i++) {
        int u,v;
        ll a,b;
        cin >> u >> v >> a >> b;
        u--;
        v--;
        G1[u].push_back(edge{v,a});
        G1[v].push_back(edge{u,a});
        G2[u].push_back(edge{v,b});
        G2[v].push_back(edge{u,b});
    }
    dijkstra1(s);
    dijkstra2(t);
    SegTree<ll> seg(V,INF,
                    [](ll a,ll b){return min(a,b);},
                    [](ll a,ll b){return b;});
    for(int i = 0;i < V;i++) {
        seg.change(i,d1[i] + d2[i]);
    }
    ll cnt = 1000000000000000;
    for(int i = 0;i < V;i++) {
        cout << cnt - seg.query(i,V) << endl;
    }
}

Measured memory_bytes: 22040