Problem:
Score : 400 points

Problem Statement

Kenkoooo is planning a trip in Republic of Snuke.
In this country, there are n cities and m trains running.
The cities are numbered 1 through n, and the i-th train connects City u_i and v_i bidirectionally.
Any city can be reached from any city by changing trains.

Two currencies are used in the country: yen and snuuk.
Any train fare can be paid by both yen and snuuk.
The fare of the i-th train is a_i yen if paid in yen, and b_i snuuk if paid in snuuk.

In a city with a money exchange office, you can change 1 yen into 1 snuuk.
However, when you do a money exchange, you have to change all your yen into snuuk.
That is, if Kenkoooo does a money exchange when he has X yen, he will then have X snuuk.
Currently, there is a money exchange office in every city, but the office in City i will shut down in i years and can never be used in and after that year.

Kenkoooo is planning to depart City s with 10^{15} yen in his pocket and head for City t, and change his yen into snuuk in some city while traveling.
It is acceptable to do the exchange in City s or City t.

Kenkoooo would like to have as much snuuk as possible when he reaches City t by making the optimal choices for the route to travel and the city to do the exchange.
For each i=0,...,n-1, find the maximum amount of snuuk that Kenkoooo has when he reaches City t if he goes on a trip from City s to City t after i years.
You can assume that the trip finishes within the year.

Constraints

2 \leq n \leq 10^5

1 \leq m \leq 10^5

1 \leq s,t \leq n

s \neq t

1 \leq u_i < v_i \leq n

1 \leq a_i,b_i \leq 10^9

If i\neq j, then u_i \neq u_j or v_i \neq v_j.

Any city can be reached from any city by changing trains.

All values in input are integers.

Input

Input is given from Standard Input in the following format:

n m s t
u_1 v_1 a_1 b_1
:
u_m v_m a_m b_m

Output

Print n lines.
In the i-th line, print the maximum amount of snuuk that Kenkoooo has when he reaches City t if he goes on a trip from City s to City t after i-1 years.

Sample Input 1

4 3 2 3
1 4 1 100
1 2 1 10
1 3 20 1

Sample Output 1

999999999999998
999999999999989
999999999999979
999999999999897

After 0 years, it is optimal to do the exchange in City 1.

After 1 years, it is optimal to do the exchange in City 2.

Note that City 1 can still be visited even after the exchange office is closed.
Also note that, if it was allowed to keep 1 yen when do the exchange in City 2 and change the remaining yen into snuuk, we could reach City 3 with 999999999999998 snuuk, but this is NOT allowed.

After 2 years, it is optimal to do the exchange in City 3.

After 3 years, it is optimal to do the exchange in City 4.
Note that the same train can be used multiple times.

Sample Input 2

8 12 3 8
2 8 685087149 857180777
6 7 298270585 209942236
2 4 346080035 234079976
2 5 131857300 22507157
4 8 30723332 173476334
2 6 480845267 448565596
1 4 181424400 548830121
4 5 57429995 195056405
7 8 160277628 479932440
1 6 475692952 203530153
3 5 336869679 160714712
2 7 389775999 199123879

Sample Output 2

999999574976994
999999574976994
999999574976994
999999574976994
999999574976994
999999574976994
999999574976994
999999574976994

Solution in C# (Mono 4.6.2.0) (judge verdict: Wrong Answer)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CompetitiveProgCsLib
{
	class MainProg
	{
		static string R => Console.ReadLine();
		static int RI => int.Parse(R);
		static double RD => double.Parse(R);
		static int[] RIs => R.Split(' ').Select(int.Parse).ToArray();
		static double[] RDs => R.Split(' ').Select(double.Parse).ToArray();
		static void Out(object obj) => Console.WriteLine(obj);
		static void OutLine<T>(IEnumerable<T> obj, string separateChar) => Out(String.Join(separateChar, obj));
		static void Outb(bool b) => Out(b ? "Yes" : "No");
		static void OutB(bool b) => Out(b ? "YES" : "NO");
		static bool IsIn(int y, int x, int h, int w) => 0 <= x && x < w && 0 <= y && y < h;

		static void Main(string[] args)
		{
			var nm = RIs;
			var n = nm[0];
			var m = nm[1];
			var s = nm[2];
			var t = nm[3];
			ShortestPathProblem gs = new ShortestPathProblem(n);
			ShortestPathProblem gt = new ShortestPathProblem(n);
			for (int i = 0; i < m; i++)
			{
				var uv = RIs;
				gs.addEdge(uv[0] - 1, uv[1] - 1, uv[2]);
				gt.addEdge(uv[0] - 1, uv[1] - 1, uv[3]);
				gs.addEdge(uv[1] - 1, uv[0] - 1, uv[2]);
				gt.addEdge(uv[1] - 1, uv[0] - 1, uv[3]);
			}
			var smin = gs.GetShortestCost(s - 1);
			var tmin = gt.GetShortestCost(t - 1);
			var sum = new int[n];
			int min_cost = int.MaxValue;
			for (int i = n - 1; i >= 0; i--)
			{
				sum[i] = smin[i] + tmin[i];
				min_cost = Math.Min(sum[i], min_cost);
				if (min_cost < sum[i]) sum[i] = min_cost;
			}

			for (int i = 0; i < n; i++)
			{
				Out(1000000000000000L - sum[i]);
			}
		}

		public class ShortestPathProblem
		{
			/// <summary>
			/// 辺を隣接リストで持つ
			/// </summary>
			private Dictionary<int, int>[] edges;
			public int Size
			{
				get
				{
					return edges.Length;
				}
			}

			public ShortestPathProblem(int n)
			{
				edges = (new Dictionary<int, int>[n]).Select(e => new Dictionary<int, int>()).ToArray();
			}

			/// <summary>
			/// uからvへの重みwの有向辺を加える
			/// </summary>
			/// <param name="u"></param>
			/// <param name="v"></param>
			/// <param name="w"></param>
			public void addEdge(int u, int v, int w)
			{
				edges[u].Add(v, w);
			}

			/// <summary>
			/// uからvへの有向辺を削除する
			/// </summary>
			/// <param name="u"></param>
			/// <param name="v"></param>
			public void removeEdge(int u, int v)
			{
				edges[u].Remove(v);
			}

			/// <summary>
			/// sからtへのコストを求める
			/// </summary>
			/// <param name="s"></param>
			/// <param name="t"></param>
			/// <returns></returns>
			public int GetShortestCost(int s, int t)
			{
				var visited = (new bool[Size]).Select(x => x = false).ToArray();
				PriorityQueue<CurrentState> priorityQueue = new PriorityQueue<CurrentState>();
				priorityQueue.Push(new CurrentState(s, 0));
				while (priorityQueue.Length != 0)
				{
					var state = priorityQueue.Pop();
					if (state.position == t) return state.weight;
					if (visited[state.position]) continue;
					visited[state.position] = true;
					foreach (var e in edges[state.position])
					{
						priorityQueue.Push(new CurrentState(e.Key, state.weight + e.Value));
					}
				}
				//unsolved
				return -1;
			}

			/// <summary>
			/// sから全点への最小コストを求める
			/// </summary>
			/// <param name="s"></param>
			/// <returns></returns>
			public int[] GetShortestCost(int s)
			{
				var visited = (new bool[Size]).Select(x => x = false).ToArray();
				var cost = new int[Size];
				PriorityQueue<CurrentState> priorityQueue = new PriorityQueue<CurrentState>();
				priorityQueue.Push(new CurrentState(s, 0));
				while (priorityQueue.Length != 0)
				{
					var state = priorityQueue.Pop();
					if (visited[state.position]) continue;
					visited[state.position] = true;
					cost[state.position] = state.weight;
					foreach (var e in edges[state.position])
					{
						priorityQueue.Push(new CurrentState(e.Key, state.weight + e.Value));
					}
				}
				//unsolved
				return cost;
			}

			/// <summary>
			/// sからtへのパスを求める
			/// </summary>
			/// <param name="s"></param>
			/// <param name="t"></param>
			/// <returns></returns>
			public IEnumerable<int> GetShortestPath(int s, int t)
			{
				var visited = (new int[Size]).Select(x => x = -1).ToArray();
				PriorityQueue<CurrentState> priorityQueue = new PriorityQueue<CurrentState>();
				priorityQueue.Push(new CurrentState(s, 0, s));
				while (priorityQueue.Length != 0)
				{
					var state = priorityQueue.Pop();
					if (state.position == t)
					{
						var ans = new List<int>();
						int current_pos = t;
						while (current_pos != s)
						{
							ans.Add(current_pos);
							current_pos = visited[current_pos];
						}
						ans.Add(s);
						ans.Reverse();
						return ans;
					}
					if (visited[state.position] != -1) continue;
					visited[state.position] = state.previous;
					foreach (var e in edges[state.position])
					{
						priorityQueue.Push(new CurrentState(e.Key, state.weight + e.Value, state.position));
					}
				}
				//unsolved
				return null;
			}

			public class CurrentState : IComparable
			{
				public CurrentState(int pos, int w, int pre = -1)
				{
					position = pos;
					weight = w;
					previous = pre;
				}
				public readonly int position;
				public readonly int weight;
				public readonly int previous;

				public int CompareTo(object obj)
				{
					return weight.CompareTo(((CurrentState)obj).weight);
				}
			}
		}

		public class PriorityQueue<T> where T : IComparable
		{
			#region member
			private List<T> list;
			private bool reverse;
			#endregion

			#region constructor
			/// <summary>
			/// 
			/// </summary>
			/// <param name="isReverse">定義された順序の逆で評価する</param>
			public PriorityQueue(bool isReverse = false)
			{
				list = new List<T>();
				reverse = isReverse;
			}
			#endregion

			#region private method
			private bool compare(T a, T b)
			{
				return reverse ^ a.CompareTo(b) > 0;
			}

			private void swap(int a, int b)
			{
				T tmp = list[a];
				list[a] = list[b];
				list[b] = tmp;
			}
			#endregion

			#region public method
			/// <summary>
			/// 要素を追加する
			/// </summary>
			/// <param name="item">追加する要素</param>
			public void Push(T item)
			{
				if (Length < list.Count) list[Length] = item;
				else list.Add(item);
				var pos = Length++;
				while (pos != 0)
				{
					var parent = (pos + 1) / 2 - 1;
					if (compare(list[pos], list[parent])) break;
					swap(pos, parent);
					pos = parent;
				}
			}

			/// <summary>
			/// 要素を追加する
			/// </summary>
			/// <param name="items">追加する要素の列</param>
			public void Push(IEnumerable<T> items)
			{
				foreach (var item in items)
				{
					Push(item);
				}
			}

			/// <summary>
			/// 値を確認する
			/// </summary>
			/// <returns></returns>
			public T Peek()
			{
				return list[0];
			}

			/// <summary>
			/// 値を取り出す
			/// </summary>
			/// <returns></returns>
			public T Pop()
			{
				var ret = Peek();
				var pos = 0;
				list[0] = list[--Length];
				while (2 * pos + 1 < Length)
				{
					var child = 2 * pos + 1;
					var child_other = 2 * pos + 2;
					if (child_other < Length && compare(list[child], list[child_other]))
					{
						child = child_other;
					}
					if (compare(list[child], list[pos])) break;
					swap(pos, child);
					pos = child;
				}
				return ret;
			}

			/// <summary>
			/// クリアする
			/// </summary>
			public void Clear()
			{
				list.Clear();
			}
			#endregion

			#region property
			/// <summary>
			/// 要素の長さを取得する
			/// </summary>
			public int Length
			{
				get;
				private set;
			}
			#endregion
		}
	}
}