#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <climits>
#include <vector>
#include <string>
#include <queue>
#include <deque>
#include <list>
#include <stack>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>

#define int long long
#define MOD7 1000000007
#define MOD9 1000000009

#define rep(i, n) for (int i = 0; i < (n); i++)
#define itrep(i, a) for (auto i = (a).begin(); i != (a).end(); i++)
#define REP(i, a, n) for (int i = (a); i <= (n); i++)
#define all(a) (a).begin(), (a).end()
#define mp(a, b) make_pair((a), (b))

using namespace std;

int dx[4] = { 1, 0, -1, 0 };
int dy[4] = { 0, -1, 0, 1 };

template<class T> void inputVector(vector<T>& v, int n) {
    v.resize(n);
    for (int i = 0; i < v.size(); i++) cin >> v[i];
}

class Graph {
private:
	// キュー用ノード情報
	struct QInfo {
		int nodeNum;    // ノード番号
		long long dist;	    // 距離

		// コンストラクタ
		QInfo(int argNum, long long argDist) {
			nodeNum = argNum;
			dist = argDist;
		}
		// 演算子オーバーロード
		bool operator<(const QInfo& a) const {
			return dist > a.dist;
		}
	};

public:
	// エッジの情報
	struct Edge {
		int next;	    	// 遷移先のノード
		long long weight;	// エッジの重み

		// コンストラクタ
		Edge() {
			next = -1;
			weight = 0;
		}
		Edge(int argNext, int argWeight) {
			next = argNext;
			weight = argWeight;
		}
	};
	// ノードの情報
	struct Node {
		long long dist;	    // ダイクストラ用距離
		vector<Edge> edge;  // 接続するエッジ情報
	};

	// ノードの配列
	vector<Node> node;

	/*
	/  コンストラクタ
	/  - 引数で指定された個数だけノードを作成
	*/
	Graph(int num) {
		for (int i = 0; i < num; i++) {
			node.push_back(Node());
		}
	}

	/*
	/  addNode
	/  - ノードを追加
	/   num : 追加する個数
	*/
	void addNode(int num) {
		for (int i = 0; i < num; i++) {
			node.push_back(Node());
		}
	}

	/*
	/  makeEdge
	/  - エッジを作る
	/   prevNode : 接続するノード番号
	/   nextNode : 接続するノード番号
	/   weight   : エッジの重み
	/   flagBidirect : 逆向きのエッジも作るか
	*/
	void makeEdge(int prevNode, int nextNode, long long weight, bool flagBidirect) {
		node[prevNode].edge.push_back(Edge(nextNode, weight));
		if (flagBidirect) {
			node[nextNode].edge.push_back(Edge(prevNode, weight));
		}
	}

	/*
	/  deleteEdge
	/  - エッジを削除する
	/   prevNode : 接続するノード番号
	/   nextNode : 接続するノード番号
	/   flagBidirect : 逆向きにも作用させるか
	/   返り値 : 削除に成功したかどうか
	*/
	bool deleteEdge(int prevNode, int nextNode, bool flagBidirect) {
		bool flagDelete = false;
		vector<Edge>::iterator it;
		// prevNode -> nextNode を削除
		for (it = node[prevNode].edge.begin(); it != node[prevNode].edge.end(); it++) {
			if ((*it).next == nextNode) {
				node[prevNode].edge.erase(it);
				it--;
				flagDelete = true;
			}
		}

		if (!flagBidirect) return flagDelete;

		// nextNode -> prevNode を削除
		for (it = node[nextNode].edge.begin(); it != node[nextNode].edge.end(); it++) {
			if ((*it).next == prevNode) {
				node[nextNode].edge.erase(it);
				it--;
				flagDelete = true;
			}
		}

		return flagDelete;
	}

	/*
	/  changeWeight
	/  - エッジの重さを変更する
	/   prevNode : 遷移前のノード番号
	/   nextNode : 遷移後のノード番号
	/   weight   : 変更後の重み
	/   flagBidirect : 逆向きにも作用させるか
	/   返り値 : 変更に成功したかどうか
	*/
	bool changeWeight(int prevNode, int nextNode, long long weight, bool flagBidirect) {
		bool flagChange = false;
		vector<Edge>::iterator it;
		for (it = node[prevNode].edge.begin(); it != node[prevNode].edge.end(); it++) {
			if ((*it).next == nextNode) {
				(*it).weight = weight;
				flagChange = true;
			}
		}

		if (!flagBidirect) return flagChange;

		for (it = node[nextNode].edge.begin(); it != node[nextNode].edge.end(); it++) {
			if ((*it).next == prevNode) {
				(*it).weight = weight;
				flagChange = true;
			}
		}

		return flagChange;
	}

	/*
	/  dijkstra
	/  - ダイクストラ法でノード間の距離を求める
	/  - startNodeからの距離は各nodeのdistに格納される
	/  - 計算量O((E + V)logV)
	/   startNode : 出発するノード番号
	/   endNode   : ゴールのノード番号
	/   返り値 : 2点間の距離
	*/
	int dijkstra(int startNode, int endNode) {

		// 距離初期化
		for (int i = 0; i < node.size(); i++) {
			node[i].dist = LLONG_MAX;
		}
		node[startNode].dist = 0;

		priority_queue<QInfo> q;
		set<int> inq;
		q.push(QInfo(startNode, 0));
		inq.insert(startNode);
		while (!q.empty()) {
			QInfo now = q.top(); q.pop();
			Node nowNode = node[now.nodeNum];
			inq.erase(now.nodeNum);

			for (vector<Edge>::iterator it = nowNode.edge.begin(); it != nowNode.edge.end(); it++) {
				int nextNode = (*it).next;
				if (nowNode.dist + (*it).weight < node[nextNode].dist) {
					// 距離を更新
					node[nextNode].dist = nowNode.dist + (*it).weight;

					q.push(QInfo(nextNode, node[nextNode].dist));
				}
			}
		}

		return node[endNode].dist;
	}
};

int ret[100010];

signed main() {
	int n, m, s, t;
	cin >> n >> m >> s >> t;
	s--; t--;

	Graph g1(n), g2(n);

	rep(i, m) {
		int u, v, a, b;
		cin >> u >> v >> a >> b;
		u--; v--;

		g1.makeEdge(u, v, a, true);
		g2.makeEdge(u, v, b, true);
	}

	g1.dijkstra(s, 0);
	g2.dijkstra(t, 0);

	rep(i, n) {
		ret[i] = g1.node[i].dist + g2.node[i].dist;
	}

	for (int i = n - 2; i >= 0; i--) {
		ret[i] = min(ret[i], ret[i + 1]);
	}

	rep(i, n) {
		cout << 1000000000000000 - ret[i] << endl;
	}

    return 0;
}


Measured memory_bytes: 21612