// Slower C++ solution:
#include <bits/stdc++.h>



using namespace std;

typedef long long ll;

typedef vector<int> VI;



#define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i)

#define REP(i, n) FOR(i, 0, n)



//グラフの隣接リスト

VI g[100010];

VI gi[100010];

//頂点の入次数を管理

int h[100010];

signed main(void)

{

  //頂点数v、辺の数e

  int v, e;

  cin >> v >> e;

    e=v-1+e;

  REP(i, e) {

    int s, t;

    cin >> s >> t;

    s--;t--;

    //頂点sから頂点tへの有向辺

    g[s].push_back(t);

    gi[t].push_back(s);

    h[t]++;

  }



  //入次数が0の頂点の集合

  stack<int> st;



  //入次数が0の頂点であればstに追加

  REP(i, v) if(h[i] == 0) st.push(i);



  //ソートされた後のグラフ

  VI ans;

  //stがなくなるまでループ

  while(st.size()) {

    //stの集合のから一つ取り出す

    int i = st.top(); st.pop();

    ans.push_back(i);

    for(auto& j: g[i]) {

      //隣接する頂点の入次数をマイナス1

      h[j]--;

      //これによって入次数が0になればstに追加

      if(h[j] == 0) st.push(j);

    }

  }



  VI ts(v);

  {

      int cnt=0;

      for(auto i:ans){

        ts[i]=cnt++;

      }

  }

  VI tr(v,-1);

  for(auto i:ans){

      int x=-1;

      int ax=-1;

      REP(j,gi[i].size()){

          if(ts[gi[i][j]]>x){

              x=ts[gi[i][j]];

              ax=gi[i][j];

          }

      }

      tr[i]=ax+1;

  }

    REP(i,v){

      cout<<tr[i]<<endl;

    }

  return 0;

}

// Faster C++ solution for the same problem (measured speedup: 6.310820812316625x):
#include<bits/stdc++.h>

using namespace std;

#define ll long long

#define FOR(i,n,m) for(int i=(n);i<(m);i++)

#define REP(i,n) FOR(i,0,n)

#define REPR(i,n) for(int i=(n);i>=0;i--)

#define all(vec) vec.begin(),vec.end()

using vi=vector<int>;

using vvi=vector<vi>;

using vl=vector<ll>;

using vvl=vector<vl>;

using P=pair<ll,ll>;

using PP=pair<ll,P>;

using vp=vector<P>;

using vpp=vector<PP>;

using vs=vector<string>;

#define fi first

#define se second

#define pb push_back

template<class T>bool chmax(T &a,const T &b){if(a<b){a=b;return true;}return false;}

template<class T>bool chmin(T &a,const T &b){if(a>b){a=b;return true;}return false;}

const ll MOD=1000000007LL;

const int INF=1<<30;

const ll LINF=1LL<<60;

struct DAG{

    int V;

    vector<vector<int>> G;

    vector<int> in;

    DAG(int V):V(V),G(V),in(V){}

    void add_edge(int f,int t){

        G[f].push_back(t);

        in[t]++;

    }

    vector<int> topological_sort(){

        vector<int> res;

        stack<int> st;

        for(int i=0;i<V;i++){

            if(!in[i]){

                st.push(i);

            }

        }

        while(st.size()){

            int t=st.top();st.pop();

            res.push_back(t);

            for(int i=0;i<G[t].size();i++){

                if(!(--in[G[t][i]])){

                    st.push(G[t][i]);

                }

            }

        }

        return res;

    }

};

int main(){

    int V,E;

    cin>>V>>E;

    E+=V-1;

    DAG G(V);

    vvi inv(V);

    REP(i,E){

        int f,t;

        cin>>f>>t;

        f--;t--;

        G.add_edge(f,t);

        inv[t].pb(f);

    }

    auto tops=G.topological_sort();

    vi topl(V);

    REP(i,V){

        topl[tops[i]]=i;

    }

    vi ans(V,-1);

    REP(i,V){

        int v=tops[i];

        int x=-1;

        int vx=-1;

        REP(j,inv[v].size()){

            if(chmax(x,topl[inv[v][j]])){

                vx=inv[v][j];

            }

        }

        ans[v]=vx+1;

    }

    REP(i,V){

        cout<<ans[i]<<endl;

    }

    return 0;

}