void main(){
  import std.stdio, std.string, std.conv, std.algorithm;

  alias T=long;

  int n, m, s, t; rd(n, m, s, t);
  s--; t--;
  struct Edge{
    int to;
    T cost;
  }
  auto g_yen=new Edge[][](n);
  auto g_snu=new Edge[][](n);
  foreach(_; 0..m){
    int u, v; T a, b; rd(u, v, a, b);
    u--; v--;
    g_yen[u]~=Edge(v, a);
    g_yen[v]~=Edge(u, a);
    g_snu[u]~=Edge(v, b);
    g_snu[v]~=Edge(u, b);
  }

  const T inf=1e18.to!(long);
  T[] dijkstra(Edge[][] g, int s){
    auto d=new T[](n);
    fill(d, inf);
    struct P{int v; T d;}
    import std.container;
    // auto Q=new RedBlackTree!(P, "a.d<b.d", true);
    auto Q=new MyBinaryHeap!(P, "a.d<b.d");
    Q.insert(P(s, 0)); d[s]=0;
    while(Q.empty==false){
      auto cur=Q.front; Q.removeFront;
      foreach(e; g[cur.v]){
        if(d[e.to]<=d[cur.v]+e.cost) continue;
        d[e.to]=d[cur.v]+e.cost;
        Q.insert(P(e.to, d[e.to]));
      }
    }
    return d;
  }

  auto d_yen=dijkstra(g_yen, s),
       d_snu=dijkstra(g_snu, t);
  auto ans=new long[](n);
  foreach_reverse(i; 0..n){
    ans[i]=1e15.to!(long)-d_yen[i]-d_snu[i];
    if(i+1<n) chmax(ans[i], ans[i+1]);
  }
  writefln("%(%s\n%)", ans);
}

void chmax(Type)(ref Type l, Type r){if(l<r)l=r;}

void rd(T...)(ref T x){
  import std.stdio, std.string, std.conv;
  auto l=readln.split;
  assert(l.length==x.length);
  foreach(i, ref e; x) e=l[i].to!(typeof(e));
}
import std.functional : binaryFun;

class MyBinaryHeap(T, alias less = "a<b")
    if (is(typeof(binaryFun!less(T.init, T.init))))
{
  import std.range.primitives : _front = front, _back = back, _empty = empty,
    popBack;
  import std.exception : enforce;
  import std.algorithm : each, swap;

  private T[] dat;
  private alias comp = binaryFun!(less);

  this(T[] arr = [])
  {
    arr.each!(x => insert(x));
  }

  void insert(T x)
  {
    size_t i = dat.length;
    dat ~= x;
    while (i > 0)
    {
      size_t p = (i - 1) / 2;
      if (comp(dat[i], dat[p]))
      {
        swap(dat[i], dat[p]);
        i = p;
      }
      else
      {
        break;
      }
    }
  }

  T front()
  {
    enforce(dat.length > 0, "Cannot call front on an empty heap.");
    return dat._front;
  }

  void removeFront()
  {
    enforce(dat.length > 0, "Cannot call removeFront on an empty heap.");
    swap(dat._front, dat._back);
    dat.popBack;
    size_t len = dat.length;
    size_t i = 0;
    while (i * 2 + 1 < len)
    {
      if (i * 2 + 2 < len)
      {
        // 左右で強いほうの子と比べる
        size_t j = comp(dat[i * 2 + 1], dat[i * 2 + 2]) ? i * 2 + 1 : i * 2 + 2;
        if (comp(dat[j], dat[i]))
        {
          swap(dat[j], dat[i]);
          i = j;
        }
        else
        {
          break;
        }
      }
      else // 左の子しかない
      {
        if (comp(dat[i * 2 + 1], dat[i]))
        {
          swap(dat[i * 2 + 1], dat[i]);
          i = i * 2 + 1;
        }
        else
        {
          break;
        }
      }
    }
  }

  bool empty()
  {
    return dat._empty;
  }
}
