import std.stdio, std.conv, std.string, std.bigint;
import std.math, std.random, std.datetime;
import std.array, std.range, std.algorithm, std.container, std.format;
string read(){ static string[] ss; while(!ss.length) ss = readln.chomp.split; string res = ss[0]; ss.popFront; return res; }

/*

誰の子にもなっていない頂点は、根

１人の子になっている頂点は、それが親

２人以上の子になっている頂点は親が不明
親の候補の個数を記憶

根から、幅優先探索でたどっていく

親が不明の頂点についたらそこで止まる。探索はしない
（早くついたということはそれはショートカットルートだった）
親の候補の個数を減らす
１だったらそれが本当の親

*/

class Node{
	Node parent;
	Node[] kids;
	Node[] parents;
	long count;
	long id;
	this(long id){
		this.id = id;
	}
}

class X{
	Node from;
	Node to;
	this(Node from, Node to){
		this.from = from, this.to = to;
	}
}

void main(){
	long n = read.to!long;
	long m = read.to!long;
	
	Node[] nodes;
	foreach(i; 0 .. n) nodes ~= new Node(i);
	
	foreach(i; 0 .. n - 1 + m){
		long a = read.to!long - 1;
		long b = read.to!long - 1;
		
		nodes[a].kids ~= nodes[b];
		nodes[b].parents ~= nodes[a];
	}
	
	Node root;
	foreach(nd; nodes){
		if(nd.parents.length == 0) nd.parent = null, root = nd;
		else nd.count = nd.parents.length;
	}
	
	X[] queue;
	long ix = 0;
	foreach(nd; root.kids) queue ~= new X(root, nd);
	while(ix < queue.length){
		X x = queue[ix];
		if(x.to.count == 1){
			x.to.parent = x.from;
			foreach(nd; x.to.kids) queue ~= new X(x.to, nd);
		}
		else x.to.count -= 1;
		
		ix += 1;
	}
	
	foreach(nd; nodes){
		if(nd.parent) writeln(nd.parent.id + 1);
		else writeln(0);
	}
}
