#include <iostream>

#include <cstdio>
#include <cstdlib>

#include <stdint.h>

typedef uint8_t  u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef int8_t   s8;
typedef int16_t  s16;
typedef int32_t  s32;
typedef int64_t  s64;

const int INF = (1 << 28);
const long INFL = (1LL << 50);

class FastIO {
public:
  void flush() {
    fflush(stdin);
    fflush(stdout);
  }
  FastIO& operator >> (int &right) {
    if( scanf("%d", &right) == EOF ) {
      flush();
      exit(0);
    }
    return *this;
  }
  FastIO& operator >> (u64 &right) {
    if( scanf("%ld", &right) == EOF ) {
      flush();
      exit(0);
    }
    return *this;
  }
  FastIO& operator >> (s64 &right) {
    if( scanf("%ld", &right) == EOF ) {
      flush();
      exit(0);
    }
    return *this;
  }
  FastIO& operator >> (u32 &right) {
    if( scanf("%d", &right) == EOF ) {
      flush();
      exit(0);
    }
    return *this;
  }
  FastIO& operator >> (double &right) {
    if( scanf("%lf", &right) == EOF ) {
      flush();
      exit(0);
    }
    return *this;
  }
  FastIO& operator >> (char &right) {
    if( scanf("%c", &right) == EOF ) {
      flush();
      exit(0);
    }     
    return *this;
  }
  FastIO& operator >> (char right[]) {
    if( scanf("%s", right) == EOF ) {
      flush();
      exit(0);
    }           
    return *this;
  }  
  FastIO& operator << (const int& right) {
    printf("%d", right);
    return *this;
  }
  FastIO& operator << (const u32& right) {
    printf("%d", right);
    return *this;
  }
  FastIO& operator << (const u64& right) {
    printf("%ld", right);
    return *this;
  }
  FastIO& operator << (const s64& right) {
    printf("%ld", right);
    return *this;
  }
  FastIO& operator << (const double& right) {
    printf("%.20lf", right);
    return *this;
  }

  FastIO& operator << (const char right[]) {
    printf("%s", right);
    return *this;
  }
  
  FastIO& operator << (const char& right) {
    printf("%c", right);
    return *this;
  }
};

FastIO io;

#include <cstdint>

typedef uint32_t u32;

class void_ {
};

template<typename T>
class Weight {
protected:
  T w_;
public:
  const T& weight() const;
};

template<>
class Weight<void_> : public void_ {
};

template<typename Tweight>
const Tweight& Weight<Tweight>::weight() const {
  return w_;
}

template<typename Tweight>
class Edge : public Weight<Tweight> {
public:
  Edge();
  Edge(u32 from, u32 to);
  Edge(u32 from, u32 to, Tweight w);
  const u32& from() const;
  const u32& to() const;
  Edge reverse();
  void dump();
private:
  u32 s, t;
};

template<typename Tweight>
Edge<Tweight>::Edge() {
}

template<typename Tweight>
Edge<Tweight>::Edge(u32 from, u32 to) {
  s = from; t = to;
}

template<typename Tweight>
Edge<Tweight>::Edge(u32 from, u32 to, Tweight w) {
  s = from; t = to;
  this->w_ = w;
}

template<typename Tweight>
const u32& Edge<Tweight>::from() const {
  return s;
}

template<typename Tweight>
const u32& Edge<Tweight>::to() const {
  return t;
}

template<typename Tweight>
Edge<Tweight> Edge<Tweight>::reverse() {
  Edge res = *this;
  u32 tmp;
  tmp = s; s = t; t = tmp;
  return res;
}

template<typename Tweight, bool isdirected, u32 maxV, u32 maxE>
class Graph {
public:
  Graph();
  Graph(u32 V);
  void insert(Edge<Tweight> edge);
  u32 Vsize();
  void activate();
  Edge<Tweight>* adjust(u32 v);
  u32 adjust_size(u32 v);
private:
  Edge<Tweight> edge_[maxE];
  u32 edge_num;
  u32 vertex_num;
  u32 adjust_size_[maxV];
  u32 index[maxV];
};

template<typename T, typename U>
T Max(T arg1, U arg2) {
  T arg2T = static_cast<T>(arg2);
  if( arg1 < arg2T ) return arg2T;
  return arg1;
}

template<typename T, typename U>
T Min(T arg1, U arg2) {
  T arg2T = static_cast<T>(arg2);
  if( arg2T < arg1 ) return arg2T;
  return arg1;
}

template<typename Tweight, bool isdirected, u32 maxV, u32 maxE>
Graph<Tweight, isdirected, maxV, maxE>::Graph() {
  edge_num = 0;
  vertex_num = 0;
  for(int i = 0; i < maxV; ++i) {
    adjust_size_[i] = 0;
    index[i] = 0;
  }
}

template<typename Tweight, bool isdirected, u32 maxV, u32 maxE>
Graph<Tweight, isdirected, maxV, maxE>::Graph(u32 V) {
  edge_num = 0;
  vertex_num = V;
  for(int i = 0; i < maxV; ++i) {
    adjust_size_[i] = 0;
    index[i] = 0;
  }
}

template<typename Tweight, bool isdirected, u32 maxV, u32 maxE>
void Graph<Tweight, isdirected, maxV, maxE>::insert(Edge<Tweight> edge) {
  edge_[edge_num] = edge;
  edge_num += 1;
  if( not isdirected ) {
    edge_[edge_num] = edge.reverse();
    edge_num += 1;
  }
  vertex_num = Max(vertex_num, edge.from());
  vertex_num = Max(vertex_num, edge.to());
}

template<typename Tweight, bool isdirected, u32 maxV, u32 maxE>
void Graph<Tweight, isdirected, maxV, maxE>::activate() {
  Edge<Tweight> buffer[maxE];
  u32 E = edge_num;
  u32 count[maxV];
  for(int i = 0; i < maxV; ++i) count[i] = 0;
  for(int i = 0; i < E; ++i) {
    count[edge_[i].from()] += 1;
  }
  for(int i = 0; i < maxV; ++i) {
    adjust_size_[i] = count[i];
  }
  int t = 0;
  for(int i = 0; i < maxV; ++i) {
    t += count[i];
    count[i] = t - count[i];
    index[i] = count[i];
  }
  for(int i = 0; i < E; ++i) {
    buffer[count[edge_[i].from()]] = edge_[i];
    count[edge_[i].from()] += 1;
  }
  for(int i = 0; i < E; ++i) {
    edge_[i] = buffer[i];
  }
}

template<typename Tweight, bool isdirected, u32 maxV, u32 maxE>
Edge<Tweight>* Graph<Tweight, isdirected, maxV, maxE>::adjust(u32 v) {
  return &edge_[index[v]];
}

template<typename Tweight, bool isdirected, u32 maxV, u32 maxE>
u32 Graph<Tweight, isdirected, maxV, maxE>::adjust_size(u32 v) {
  return adjust_size_[v];
}

template<typename Tweight, bool isdirected, u32 maxV, u32 maxE>
u32 Graph<Tweight, isdirected, maxV, maxE>::Vsize() {
  return vertex_num;
}

u64 rdtsc() {
  u64 u, l;
  __asm__ volatile ("rdtsc" : "=a" (l), "=d" (u));
  return (u << 32) | l;
}

template<typename Tweight, u32 maxV, u32 maxE>
void topological_sort(Graph<Tweight, true, maxV, maxE>& graph, int *id) {
  bool used[maxV] = {};
  int k = graph.Vsize();
  for(int i = 1; i <= graph.Vsize(); ++i) {
    if( not used[i] ) {
      topological_sort_dfs(graph, id, used, i, k);
    }
  }
}

template<typename Tweight, u32 maxV, u32 maxE>
void topological_sort_dfs(Graph<Tweight, true, maxV, maxE>& graph, int *id, bool *used, int i, int& k) {
  if( used[i] ) return;
  used[i] = true;
  u32 n = graph.adjust_size(i);
  for(int j = 0; j < n; ++j) {
    topological_sort_dfs(graph, id, used, graph.adjust(i)[j].to(), k);
  }
  id[k] = i;
  k -= 1;
}

class Solver {
private:
public:
  void solve() {
    int V, E;
    std::cin >> V >> E;
    Edge<void_> edge;
    Graph<void_, true, 10010, 100100> graph(V);
    for(int i = 0; i < E; ++i) {
      int s, t;
      std::cin >> s >> t;
      graph.insert(Edge<void_>(s + 1, t + 1));
    }
    graph.activate();
    int id[10100] = {};
    topological_sort(graph, id);
    for(int i = 1; i <= V; ++i) {
      //if( not ( 1 <= id[i] and id[i] <= V ) ) exit(1);
      std::cout << id[i] - 1 << std::endl;
    }
  }
};

int main() {

  Solver solver;
  solver.solve();
  
  return 0;
}

Measured memory_bytes: 3976