// #define _GLIBCXX_DEBUG // for STL debug (optional)
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <string>
#include <cstring>
#include <deque>
#include <list>
#include <queue>
#include <stack>
#include <vector>
#include <utility>
#include <algorithm>
#include <map>
#include <set>
#include <complex>
#include <cmath>
#include <limits>
#include <cfloat>
#include <climits>
#include <ctime>
#include <cassert>
#include <numeric>
#include <fstream>
#include <functional>
#include <bitset>
using namespace std;

#define debug(...) fprintf(stderr, __VA_ARGS__)
#define int long long int
 
template<typename T> void chmax(T &a, T b) {a = max(a, b);}
template<typename T> void chmin(T &a, T b) {a = min(a, b);}
template<typename T> void chadd(T &a, T b) {a = a + b;}
 
typedef pair<int, int> pii;
typedef long long ll;
 
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
const ll INF = 1001001001001001LL;
const ll MOD = 1000000007LL;

int N, M;

// 移動元と行先と辺のコストを記録する構造体
template <typename T>
struct Edge {
    int from, to;
    T cost;
    Edge(int s, T d) : to(s), cost(d) {}
    Edge(int f, int s, T d) : from(f), to(s), cost(d) {}

    bool operator<(const Edge &e) const {
        return cost < e.cost;
    }
    bool operator>(const Edge &e) const {
        return cost > e.cost;
    }
};

template <typename T>
using Graph = vector< vector< Edge<T> > >;

// トポロジカルソート 各種

// 2016/12/27 追記: 有向グラフの閉路検査はトポロジカルソートで容易に行える。
// → 閉路があれば入次数 0 になりえない頂点が存在する
// → トポロジカルソートした結果の vector の size が頂点数と等しくなければ閉路が存在

#define rep(i,a,n) for(int (i)=(a); (i)<(n); (i)++)
// Kahnのトポロジカルソートアルゴリズム (Verified: AOJ GRL_4_B: Topological Sort)
template <typename T>
vector<int> tpsort_Kahn(const vector< vector< Edge<T> > > &g) {
    const int V = g.size();
    vector<int> indeg(V, 0);
    stack<int> S;

    rep(i,0,V) rep(j,0,g[i].size())
        indeg[ g[i][j].to ]++;
    rep(i,0,V) if(indeg[i] == 0) S.push(i);

    vector<int> ans;
    while(S.size() > 0) {
        int u = S.top(); S.pop();
        ans.push_back(u);
        rep(i,0,g[u].size()) {
            indeg[ g[u][i].to ]--;
            if(indeg[ g[u][i].to ] ==  0)
                S.push( g[u][i].to );
        }
    }
    return ans;
}

signed main() {
    cin >> N >> M;
    M += N-1;
    Graph<int> G(N);

    vector<int> level(N);
    vector<int> fr(M), tt(M);
    for(int i=0; i<M; i++) {
        int u, v; cin >> u >> v;
        u--; v--;
        fr[i] = u, tt[i] = v;
        G[u].push_back(Edge<int>(v, 1));
    }

    auto res = tpsort_Kahn(G);
    for(int i=0; i<N; i++) {
        int id = res[i];
        // fprintf(stderr, "tp[%lld] = %lld, level = %lld\n", i, id, level[id]);
        for(auto e : G[id]) {
            int to = e.to;
            chmax(level[to], level[id] + 1);
        }
    }

    vector<int> ans(N);
    for(int i=0; i<M; i++) {
        int u = fr[i], v = tt[i];
        // fprintf(stderr, "level[%lld] = %lld, level[%lld] = %lld\n", u, level[u], v, level[v]);
        if(level[u] + 1 == level[v]) {
            // fprintf(stderr, "ans[%lld] = %lld\n", v, u + 1);
            ans[v] = u + 1;
        }
    }

    for(int i=0; i<N; i++) {
        cout << ans[i] << endl;
    }
    return 0;
}


Measured memory_bytes: 11760