// Slower C++ solution:
#include <iostream>

#include <sstream>

#include <string>

#include <vector>

#include <stack>

#include <queue>

#include <set>

#include <map>

#include <numeric>

#include <algorithm>

#include <cstdio>

#include <cstdlib>

#include <cstring>

#include <cctype>

#include <cmath>

#include <cassert>

#include <cstdarg>

#include <sys/time.h>

#include <fstream>

//#include "cout.h"



using namespace std;



#define SZ(x) ((int)x.size())

#define MSET(x,a) memset(x, a, (int)sizeof(x))

#define PB push_back

#define VI vector < int >

#define PII pair < int, int >

#define LL long long

#define FOR(i,a,b) for (int i = (a); i < (b); i++)

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

#define ALL(v) (v).begin(), (v).end()

#define FIT(it,v) for (__typeof((v).begin()) it = (v).begin(); it != (v).end(); it++)

#define OUT(A) cout << #A << " = "<< (A) << endl

#define OUT2(A, B) cout << "(" << #A << ", " << #B << ") = (" << (A) << ", "<< (B) << ")" << endl

template<class T> void chmin(T &t, T f) { if (t > f) t = f; }

template<class T> void chmax(T &t, T f) { if (t < f) t = f; }



#define present(c, e) ((c).find((e)) != (c).end())

#define cpresent(c, e) (find(ALL(c), (e)) != (c).end())



int n, m;

int r;

vector<int> e[100010];

vector<int> topo;

// bool used[100010];

int in[100010];

int parent[100010];



void init() {



}



// void dfs(int i) {

//   if (used[i]) return;

//   used[i] = true;

//   REP(j, SZ(e[i])) dfs(e[i][j]);

//   topo.push_back(i);

// }

//

// void makeTopo() {

//   topo.clear();

//   REP(i, n) dfs(i);

//   reverse(ALL(topo));

// }



void input() {

  REP(i, 100010) {

    e[i].clear();

    parent[i] = -1;

    in[i] = 0;

  }

  cin >> n >> m;

  REP(i, n+m-1) {

    int a, b;

    cin >> a >> b;

    a--;

    b--;

    e[a].push_back(b);

    in[b]++;

  }

  queue<int> q;

  REP(i, n) if (in[i] == 0) q.push(i);

  while(SZ(q)) {

    int i = q.front();

    topo.push_back(i);

    q.pop();

    REP(j, SZ(e[i])) {

      in[e[i][j]]--;

      if (in[e[i][j]] == 0) q.push(e[i][j]);

    }

  }

  REP(i, n) {

    REP(j, SZ(e[topo[i]])) {

      parent[e[topo[i]][j]] = topo[i];

    }

  }

  REP(i, n) cout << parent[i] + 1 << endl;

}



void solve() {



}



int main() {

	init();

	input();

	solve();

	return 0;

}


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

using namespace std;

typedef long long ll;

typedef pair<int,int> P;

typedef pair<int,P> P1;

typedef pair<P,P> P2;

#define pu push

#define pb push_back

#define mp make_pair

#define eps 1e-7

#define INF 1000000000

#define mod 1000000007

#define fi first

#define sc second

#define rep(i,x) for(int i=0;i<x;i++)

#define repn(i,x) for(int i=1;i<=x;i++)

#define SORT(x) sort(x.begin(),x.end())

#define ERASE(x) x.erase(unique(x.begin(),x.end()),x.end())

#define POSL(x,v) (lower_bound(x.begin(),x.end(),v)-x.begin())

#define POSU(x,v) (upper_bound(x.begin(),x.end(),v)-x.begin())

int n,m;

vector<int>edge[100005];

int in[100005];

queue<int>que;

int ans[100005];

int main(){

	scanf("%d%d",&n,&m);

	m += n-1;

	rep(i,m){

		int a,b; scanf("%d%d",&a,&b);

		edge[a].pb(b);

		in[b]++;

	}

	repn(i,n) if(in[i]==0) que.push(i);

	while(!que.empty()){

		int q = que.front(); que.pop();

		for(int i=0;i<edge[q].size();i++){

			int to = edge[q][i];

			in[to]--;

			if(in[to] == 0) {ans[to] = q; que.push(to);}

		}

	}

	repn(i,n) printf("%d\n",ans[i]);

}