#include <stdexcept>
#include <string>
#include <algorithm>
#include <iostream>
#include <cstddef>
#include <vector>
#include <queue>
namespace loquat {
using vertex_t = size_t;
}
namespace loquat {
namespace edge_param {
struct to_ {
	vertex_t to;
	explicit to_(vertex_t t = 0)
		: to(t)
	{ }
};
}
namespace detail {
template <typename T, typename... Params>
struct edge_param_wrapper : public T, edge_param_wrapper<Params...> {
};
template <typename T>
struct edge_param_wrapper<T> : public T {
	using self_type = edge_param_wrapper<T>;
	edge_param_wrapper(const self_type& e)
		: T(e)
	{ }
	template <typename U>
	explicit edge_param_wrapper(U&& x)
		: T(std::forward<U>(x))
	{ }
};
}
template <typename... Params>
struct edge : public detail::edge_param_wrapper<edge_param::to_, Params...> {
	using self_type = edge<Params...>;
	using wrapper_type = detail::edge_param_wrapper<edge_param::to_, Params...>;
	edge(const self_type& e)
		: wrapper_type(static_cast<const wrapper_type&>(e))
	{ }
	template <typename... Args>
	explicit edge(vertex_t to, Args&&... rest)
		: wrapper_type(to, std::forward<Args>(rest)...)
	{ }
};
}
namespace loquat {
template <typename EdgeType>
class adjacency_list {
public:
	using edge_type = EdgeType;
	using edge_list = std::vector<edge_type>;
private:
	std::vector<std::vector<EdgeType>> m_edges;
public:
	explicit adjacency_list(size_t n)
		: m_edges(n)
	{ }
	size_t size() const {
		return m_edges.size();
	}
	const edge_list& operator[](vertex_t u) const {
		return m_edges[u];
	}
	edge_list& operator[](vertex_t u){
		return m_edges[u];
	}
	template <typename... Args>
	void add_edge(vertex_t from, Args&&... args){
		m_edges[from].emplace_back(std::forward<Args>(args)...);
	}
};
}
namespace loquat {
class no_solution_error : public std::runtime_error {
public:
	explicit no_solution_error(const char *what)
		: std::runtime_error(what)
	{ }
};
}
namespace loquat {
template <typename EdgeType>
std::vector<vertex_t> topological_sort(const adjacency_list<EdgeType>& graph){
	const size_t n = graph.size();
	std::vector<size_t> input_degrees(n);
	for(vertex_t u = 0; u < n; ++u){
		for(const auto& e : graph[u]){ ++input_degrees[e.to]; }
	}
	std::queue<size_t> q;
	for(vertex_t v = 0; v < n; ++v){
		if(input_degrees[v] == 0){ q.push(v); }
	}
	std::vector<vertex_t> order;
	order.reserve(n);
	while(!q.empty()){
		const auto u = q.front();
		q.pop();
		order.push_back(u);
		for(const auto& e : graph[u]){
			const auto v = e.to;
			if(--input_degrees[v] == 0){ q.push(v); }
		}
	}
	if(order.size() != n){
		throw no_solution_error("graph is not a DAG");
	}
	return order;
}
}
using namespace std;
using edge = loquat::edge<>;
int main(){
	ios_base::sync_with_stdio(false);
	int n, m;
	cin >> n >> m;
	loquat::adjacency_list<edge> g(n), ig(n);
	for(int i = 0; i < n + m - 1; ++i){
		int a, b;
		cin >> a >> b;
		--a; --b;
		g.add_edge(a, b);
		ig.add_edge(b, a);
	}
	const auto topo = loquat::topological_sort(g);
	const int root = topo[0];
	vector<int> dist(n, n), parent(n, -1);
	dist[root] = 0;
	parent[root] = root;
	for(const auto u : topo){
		if(u == root){ continue; }
		int best_v = n, best_d = -1;
		for(const auto& e : ig[u]){
			const auto v = e.to;
			if(dist[v] > best_d){
				best_v = v;
				best_d = dist[v];
			}
		}
		parent[u] = best_v;
		dist[u] = best_d + 1;
	}
	for(int i = 0; i < n; ++i){
		if(parent[i] == i){
			cout << 0 << "\n";
		}else{
			cout << parent[i] + 1 << "\n";
		}
	}
	return 0;
}


Measured memory_bytes: 13296