#include <bits/stdc++.h>
//#define int long long

using namespace std;
using LL = long long;
using P = pair<int, int>;

#define FOR(i, a, n) for(int i = (int)(a); i < (int)(n); ++i)
#define REP(i, n) FOR(i, 0, n)

#define pb(a) push_back(a)
#define all(x) (x).begin(),(x).end()

template<typename T>
vector<T> make_v(size_t a){return vector<T>(a);}
template<typename T,typename... Ts>
auto make_v(size_t a, Ts... ts) {return vector<decltype(make_v<T>(ts...))>(a, make_v<T>(ts...)); }

template<typename T,typename V>
typename enable_if<is_class<T>::value == 0>::type
fill_v(T &t, const V &v){ t = v; }

template<typename T,typename V>
typename enable_if<is_class<T>::value != 0>::type
fill_v(T &t, const V &v){ for(auto &e : t) fill_v(e, v); }

const int INF = (int)1e9;
const LL INFL = (LL)1e18;
const int MOD = 1e9 + 7;

// 単一始点最短経路(ダイクストラ法)
// 時間計算量はO((V+E)logV)
// 使用例:
// Dijkstra<int> dij(N);
// dij.AddEdge(f, t, c);  <- fからtのコストcの辺を追加
// dij.Run(s);            <- s始点での最短経路長
// dij.cost[t]            <- Run()で求めた始点からtへの最短経路長を取得
// dij.HasPath(t)         <- Run()で求めた始点からtへのパスは存在するか
// dij.GetShortestPath(t) <- Run()で求めた始点からtへのパスを取得
template <typename T>
struct Edge
{
    int from, to;
    T cost;
    Edge(int to, T cost) : from(-1), to(to), cost(cost) {}
    Edge(int from, int to, T cost) : from(from), to(to), cost(cost) {}
};

template <typename T>
using Edges = vector<Edge<T>>;
template <typename T>
using AdjList = vector<Edges<T>>;

template <typename T>
class Dijkstra
{
  private:
    T INF = numeric_limits<T>::max() / 10;
    int V;
    AdjList<T> adj;
    vector<int> prever;

  public:
    Dijkstra(int n) : V(n + 1), adj(V), prever(vector<int>(V, -1)), cost(V, INF) {}
    vector<T> cost;
    void AddEdge(int f, int t, int c)
    {
        adj[f].push_back(Edge<T>(t, c));
    }
    bool HasPath(int t)
    {
        return cost[t] != INF;
    }
    vector<int> GetShortestPath(int t)
    {
        vector<int> path;
        for (; t != -1; t = prever[t]) path.push_back(t);
        reverse(path.begin(), path.end());
        return path;
    }
    void Run(int f)
    {
        cost.assign(V, INF);
        prever.assign(V, -1);

        using Pi = pair<T, int>;
        priority_queue<Pi, vector<Pi>, greater<Pi>> pq;

        cost[f] = 0;
        pq.push(Pi(cost[f], f));

        while (!pq.empty())
        {
            Pi currentEdge = pq.top();
            pq.pop();
            if (cost[currentEdge.second] < currentEdge.first) continue;

            for (Edge<T> tmp : adj[currentEdge.second])
            {
                T sumCost = currentEdge.first + tmp.cost;
                if (cost[tmp.to] > sumCost)
                {
                    cost[tmp.to] = sumCost;
                    prever[tmp.to] = currentEdge.second;
                    pq.push(Pi(cost[tmp.to], tmp.to));
                }
            }
        }
    }
};

signed main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    int n, m, s, t;
    cin >> n >> m >> s >> t;
    vector<int> u(m), v(m), a(m), b(m);
    REP(i, m) cin >> u[i] >> v[i] >> a[i] >> b[i];

    Dijkstra<LL> dij1(n), dij2(n);
    REP(i, m)
    {
        dij1.AddEdge(u[i]-1, v[i]-1, a[i]);
        dij1.AddEdge(v[i]-1, u[i]-1, a[i]);
        dij2.AddEdge(u[i]-1, v[i]-1, b[i]);
        dij2.AddEdge(v[i]-1, u[i]-1, b[i]);
    }
    dij1.Run(s-1);
    dij2.Run(t-1);

    vector<LL> cost(n);
    REP(i, n)
    {
        cost[i] = dij1.cost[i] + dij2.cost[i];
    }

    vector<LL> ans(n+1);
    const LL MONEY = 1e15;
    REP(i, n)
    {
        ans[n-i-1] = max(ans[n-i], MONEY - cost[n-i-1]);
    }
    REP(i, n) cout << ans[i] << endl;
}

Measured memory_bytes: 22088