Problem:
Score : 500 points

Problem Statement

There is a rooted tree (see Notes) with N vertices numbered 1 to N.
Each of the vertices, except the root, has a directed edge coming from its parent.
Note that the root may not be Vertex 1.

Takahashi has added M new directed edges to this graph.
Each of these M edges, u \rightarrow v, extends from some vertex u to its descendant v.

You are given the directed graph with N vertices and N-1+M edges after Takahashi added edges.
More specifically, you are given N-1+M pairs of integers, (A_1, B_1), ..., (A_{N-1+M}, B_{N-1+M}), which represent that the i-th edge extends from Vertex A_i to Vertex B_i.

Restore the original rooted tree.

Notes

For "tree" and other related terms in graph theory, see the article in Wikipedia, for example.

Constraints

3 \leq N

1 \leq M

N + M \leq 10^5

1 \leq A_i, B_i \leq N

A_i \neq B_i

If i \neq j, (A_i, B_i) \neq (A_j, B_j).

The graph in input can be obtained by adding M edges satisfying the condition in the problem statement to a rooted tree with N vertices.

Input

Input is given from Standard Input in the following format:

N M
A_1 B_1
:
A_{N-1+M} B_{N-1+M}

Output

Print N lines.
In the i-th line, print 0 if Vertex i is the root of the original tree, and otherwise print the integer representing the parent of Vertex i in the original tree.

Note that it can be shown that the original tree is uniquely determined.

Sample Input 1

3 1
1 2
1 3
2 3

Sample Output 1

0
1
2

The graph in this input is shown below:

It can be seen that this graph is obtained by adding the edge 1 \rightarrow 3 to the rooted tree 1 \rightarrow 2 \rightarrow 3.

Sample Input 2

6 3
2 1
2 3
4 1
4 2
6 1
2 6
4 6
6 5

Sample Output 2

6
4
2
0
6
2

Solution in C# (Mono 4.6.2.0) (judge verdict: Time Limit Exceeded)

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 T MIN<T>(params T[] args) => args.Min();
		static T MAX<T>(params T[] args) => args.Max();

		static void Main(string[] args)
		{
			var nm = RIs;
			var n = nm[0];
			var m = nm[1];
			ShortestPathProblem spp = new ShortestPathProblem(n + 1);
			var bo = new bool[n];
			var ba = new bool[n];
			for (int i = 0;i < n + m -1;i++)
			{
				var ab = RIs;
				spp.addEdge(ab[0] - 1, ab[1] - 1, 1);
				bo[ab[1] - 1] = true;
				ba[ab[0] - 1] = true;
			}
			int s = 0;
			int t = 0;
			for(int i = 0;i < n;i++)
			{
				if(!bo[i])
				{
					s = i;
				}
			}
			for (int i = 0; i < n; i++)
			{
				if (!ba[i])
				{
					spp.addEdge(i, n, 1);
				}
			}
			spp.GetShortestPath(s, n);
			spp.visited[s] = -1;
			for(int i = 0;i < n;i++)
			{
				Out(spp.visited[i] + 1);
			}
		}

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

			public int[] visited;

			public ShortestPathProblem(int n)
			{
				visited = (new int[n]).Select(x => x = -1).ToArray();
				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 void GetShortestPath(int s, int t)
			{
				var priorityQueue = new PriorityQueue<CurrentState>();
				priorityQueue.Push(new CurrentState(s, 0, s));
				while (priorityQueue.Length != 0)
				{
					var state = priorityQueue.Pop();
					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;
			}

			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();
			}

			/// <summary>
			/// 空かを返す
			/// </summary>
			/// <returns></returns>
			public bool Empty()
			{
				return Length == 0;
			}
			#endregion

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