// Slower C++ solution:
#include <iostream>

#include <string>

#include <vector>

#include <climits>

#include <algorithm>

#include <set>

#include <unordered_map>

#include <queue>

#include <iomanip>



using namespace std;

int n, m, s, t;

vector<long> u(100005);

vector<long> v(100005);

vector<long> a(100005);

vector<long> b(100005);

vector<vector<pair<long, long>>> graph(100005);



void dijkstra(long s, vector<long> &dist, bool isYen) {

  priority_queue<pair<long,long>, vector<pair<long, long>>, greater<>> queue;

  queue.push(make_pair(0, s));

  while (!queue.empty()) {

    pair<long, long> p = queue.top();

    queue.pop();

    long start = p.second;

    long d = p.first;

    if (d > dist.at(start)) {

      continue;

    }

    for (auto e : graph.at(start)) {

      long end = e.first;

      long train = e.second;

      long cost = isYen ? a.at(train) : b.at(train);

      if (dist.at(end) > d + cost) {

        dist.at(end) = d + cost;

        queue.push(make_pair(dist.at(end), end));

      }

    }

  }

}



int main() {

  cin >> n >> m >> s >> t;

  for (int i=1; i<=m; i++) {

    cin >> u.at(i) >> v.at(i) >> a.at(i) >> b.at(i);

  }



  for (int i=1; i<=m; i++) {

    graph.at(u.at(i)).push_back(make_pair(v.at(i), i));

    graph.at(v.at(i)).push_back(make_pair(u.at(i), i));

  }



  vector<long> dist1(n+1);

  vector<long> dist2(n+1);  

  for (int i=1; i<=n; i++) {

    dist1.at(i) = LONG_MAX;

    dist2.at(i) = LONG_MAX;

  }

  dist1.at(s) = 0;

  dist2.at(t) = 0;



  dijkstra(s, dist1, true);

  dijkstra(t, dist2, false);



  vector<long> dvec(n+1);

  dvec.at(n) = dist1.at(n) + dist2.at(n);

  for (int i=n-1; i>=1; i--) {

    dvec.at(i) = dist1.at(i) + dist2.at(i);

    dvec.at(i) = min(dvec.at(i), dvec.at(i+1));

  }

  long init = 1;

  for (int i=1; i<=15; i++) {

    init *= 10;

  }

  for (int i=1; i<=n; i++) {

    cout << init-dvec.at(i) << endl;

  }

}


// Faster C++ solution for the same problem (measured speedup: 1.948074360402912x):
#include <iostream>

#include <string>

#include <vector>

#include <climits>

#include <algorithm>

#include <set>

#include <unordered_map>

#include <queue>

#include <iomanip>



using namespace std;

int n, m, s, t;

vector<vector<pair<int, pair<long, long>>>> graph(100005);



void dijkstra(long s, vector<long> &dist, bool isYen) {

  priority_queue<pair<long, long>, vector<pair<long, long>>, greater<>> queue;

  queue.push(make_pair(0, s));

  while (!queue.empty()) {

    pair<long, int> p = queue.top();

    queue.pop();

    long d = p.first;

    int start = p.second;

    if (d > dist.at(start)) {

      continue;

    }

    for (auto e : graph.at(start)) {

      int end = e.first;

      long cost = isYen ? e.second.first : e.second.second;

      if (dist.at(end) > d + cost) {

        dist.at(end) = d + cost;

        queue.push(make_pair(dist.at(end), end));

      }

    }

  }

}



int main() {

  cin >> n >> m >> s >> t;

  for (int i=1; i<=m; i++) {

    int u,v;

    long a,b;

    cin >> u >> v >> a >> b;

    graph.at(u).push_back(make_pair(v, make_pair(a, b)));

    graph.at(v).push_back(make_pair(u, make_pair(a, b)));

  }



  vector<long> dist1(n+1);

  vector<long> dist2(n+1);

  for (int i=1; i<=n; i++) {

    dist1.at(i) = LONG_MAX;

    dist2.at(i) = LONG_MAX;

  }

  dist1.at(s) = 0;

  dist2.at(t) = 0;



  dijkstra(s, dist1, true);

  dijkstra(t, dist2, false);



  vector<long> dvec(n+1);

  dvec.at(n) = dist1.at(n) + dist2.at(n);

  for (int i=n-1; i>=1; i--) {

    dvec.at(i) = dist1.at(i) + dist2.at(i);

    dvec.at(i) = min(dvec.at(i), dvec.at(i+1));

  }

  long init = 1;

  for (int i=1; i<=15; i++) {

    init *= 10;

  }

  for (int i=1; i<=n; i++) {

    cout << init-dvec.at(i) << endl;

  }

}