#include <iostream>
#include <vector>
#include <queue>
using namespace std;
// 常量定义:顶点数量上限(根据题目约束设置为2e5+10,避免数组越界)
const int N = 2e5 + 10;
// 邻接表:edges[i]存储所有从顶点i出发的有向边的终点(即i→v的v)
vector<vector<int>> edges(N);
// 入度数组:in[i]表示顶点i的入度(指向i的边的数量)
int in[N];
// 全局变量:
int n, m; // n为顶点数,m为边数
queue<int> q; // 用于存储入度为0的顶点,辅助拓扑排序
vector<int> ret; // 存储最终的拓扑序列
int main()
{
// 输入顶点数n和边数m
cin >> n >> m;
// 读取m条有向边
while(m--)
{
int a, b;
cin >> a >> b; // 边的方向是a→b(a是前驱,b是后继)
edges[a].push_back(b); // 在邻接表中记录a→b的边
in[b]++; // 顶点b的入度+1(因为有一条从a指向b的边)
}
// 初始化队列:将所有入度为0的顶点加入队列(这些顶点没有前驱,可作为序列起点)
for(int i = 1; i <= n; i++)
if(in[i] == 0)
q.push(i);
// 执行Kahn算法:逐步处理入度为0的顶点,生成拓扑序列
while(q.size())
{
int a = q.front(); // 取出一个入度为0的顶点a
q.pop();
ret.push_back(a); // 将a加入拓扑序列
// 遍历a的所有后继顶点b(即所有a→b的边)
for(auto b : edges[a])
{
in[b]--; // 消除a对b的影响:b的入度-1
if(in[b] == 0) // 若b的入度变为0,说明其所有前驱已处理,可加入队列
q.push(b);
}
}
// 检查拓扑序列是否包含所有顶点
if(ret.size() == n)
{
// 输出拓扑序列(顶点间用空格分隔)
for(int i = 0; i < n - 1; i++)
{
cout << ret[i] << " ";
}
cout << ret[n - 1]; // 最后一个顶点后无空格
}
else
// 若序列长度不等于n,说明图中存在环(有顶点无法被处理),输出-1
cout << -1 << endl;
return 0;
}