#include <iostream>
#include <fstream>
#include <cmath>
#include <string>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <unordered_set>
#include <bitset>
#include <limits>
#include <algorithm>

#define MOD_BIG 1000000007
using std::string;
using std::cin;
using std::cout;
using std::cerr;
using std::endl;
using ll = long long;
using std::vector;

template<typename T> void ndarray(vector<T> &vec, int len) { vec.resize(len); }
template<typename T, typename... Args> void ndarray(vector<T> &vec, int len, Args... args) {
    vec.resize(len);
    for (auto &v : vec) ndarray(v, args...);
}

//////////////////////////////////////

enum Status {
    Not = 0,
    Now,
    End,
};

template<typename T>
struct Edge {
    int to;
    int from;
    T weight;
    Edge(int from, int to, T weight) : from(from), to(to), weight(weight) {}
};

template<typename T, typename D>
struct Graph {
    int n;
    vector<vector<Edge<T>>> g;
    vector<D> data;
    vector<Status> s;
    
    Graph(int N) : n(N), g(N+1), data(N+1), s(N+1) {}
    
    void add_edge(int from, Edge<T> e) {
        g[from].push_back(e);
    }
    void set_data(int node, D value) {
        data[node] = value;
    }
    
    //幅優先探索による最短経路
    //weightが全て同一の場合線形
    std::pair< vector<T>, vector<vector<Edge<T>>> > bfs_spp(int start) {
        vector<T> d(n+1, -1);
        vector<vector<Edge<T>>> route(n+1);
        std::queue<int> q;
        d[start] = 0;
        q.push(start);
        while(!q.empty()) {
            int v = q.front();
            q.pop();
            
            for (auto e: g[v]) {
                if (d[e.to] != -1 && d[e.to] != 0) {
                    //到達済み
                    continue;
                }
                d[e.to] = d[e.from] + 1;
                auto tmp = route[e.from];
                tmp.push_back(e);
                route[e.to] = tmp;
                q.push(e.to);
            }
        }
        return std::make_pair(d, route);
    }
    
    //ダイクストラ法
    //weightが非負の場合の最短経路
    //経路が存在しない場合、INFが返るのでオーバーフローに注意
    std::pair< vector<T>, vector<vector<Edge<T>>> > dijkstra(int start){
        using P = std::pair<T, int>;
        std::priority_queue<P, vector<P>, std::greater<P>> que;
        T T_MAX = std::numeric_limits<T>::max();
        vector<T> d(n+1, T_MAX);
        vector<vector<Edge<T>>> route(n+1);
        d[start] = 0;
        que.push(P((T)0, start));
        while(!que.empty()){
            P p = que.top();
            que.pop();
            int v = p.second;
            if(d[v] < p.first) continue;
            for(Edge<T> e : g[v]){
                if(d[e.to] > d[v] + e.weight || d[e.to] == 0){
                    d[e.to] = d[v] + e.weight;
                    auto tmp = route[e.from];
                    tmp.push_back(e);
                    route[e.to] = tmp;
                    que.push(P(d[e.to], e.to));
                }
            }
        }
        return std::make_pair(d, route);
    }
    
    //ベルマン-フォード法
    //weightを負を含む距離として最短経路を求める
    //無限ループが存在する場合、trueを1つ目に返す
    std::pair<bool, vector<T>> bellman_ford(int start) {
        T T_INF = std::numeric_limits<T>::max();
        vector<T> d(n+1, T_INF);
        vector<Edge<T>> E;
        for (int i = 0; i <= n; i++) {
            for (auto e: g[i]) {
                E.push_back(e);
            }
        }
        d[start] = 0;
        for (int i = 0; i <= n; i++) {
            for (auto e: E) {
                if (d[e.from] != T_INF && d[e.from] + e.weight < d[e.to]) {
                    //最初or別のstartからe.toへの最短路を発見
                    d[e.to] = d[e.from] + e.weight;
                    //std::cout << "new route find, to: " << e.to << ", distance: " << d[e.to] << std::endl;
                    if (i == n) {
                        //もう全ての辺はチェック済みのはずなのにまだ更新がある：無限ループあり
                        return std::make_pair(true, d);
                    }
                }
            }
        }
        return std::make_pair(false, d);
    }
    
    //あるノードに到達できるか
    //逆方向はグラフ自体逆で構成することで可能
    vector<bool> can_reach_from(int start) {
        vector<bool> reached(n+1, false);
        dfs_reach_from(start, reached);
        return reached;
    }
    void dfs_reach_from(int now, vector<bool> &reached) {
        if (reached[now]) return;
        reached[now] = true;
        for (auto e: g[now]) {
            dfs_reach_from(e.to, reached);
        }
    }
    
    //出力
    void print() {
        for (auto v: g) {
            for (auto e: v) {
                std::cout << e.from << "-(" << e.weight << ")->" << e.to << ", ";
            }
            std::cout << std::endl;
        }
    }
    
    int dfs(int now, int par, int depth);
    std::pair< vector<T>, vector<vector<Edge<T>>> > bfs(int start, ll k);
};

template<typename T, typename D>
int Graph<T, D>::dfs(int now, int par, int depth) {
    //std::cout << "searching now: " << now << std::endl;
    if (g[now].empty()) {
        //終端ノード
    }
    int res = 0;
    s[now] = Status::Now;
    for (auto e : g[now]) {
        int chi = e.to;
        if (s[chi] == Status::Now) {
            //閉路あり
        } else if (s[chi] == Status::End) {
            //探索済み(親が複数) ここを使う場合メモできないか考える
        } else {
            //未探索
            dfs(chi, now, depth+1);
        }
    }
    s[now] = Status::End;
    return res;
}

template<typename T, typename D>
std::pair< vector<T>, vector<vector<Edge<T>>> > Graph<T, D>::bfs(int start, ll k) {
    vector<T> d(n+1, -1);
    vector<vector<Edge<T>>> route(n+1);
    std::queue<int> q;
    d[start] = 0;
    q.push(start);
    while(!q.empty()) {
        int v = q.front();
        if (d[v] > k) {
            //更新可能性なし
            d[v] = -1;
            return std::make_pair(d, route);
        }
        q.pop();
        
        for (auto e: g[v]) {
            if (d[e.to] != -1 && e.to != start) {
                //到達済みがゴールにたどり着く前に出る：このスタートははずれ
                d[v] = -1;
                return std::make_pair(d, route);
            }
            d[e.to] = d[e.from] + 1;
            auto tmp = route[e.from];
            tmp.push_back(e);
            route[e.to] = tmp;
            q.push(e.to);
            if (e.to == start) {
                return std::make_pair(d, route);
            }
        }
    }
    return std::make_pair(d, route);
}


//////////////////////////////////////

int main() {
    
    int N, M;
    cin >> N >> M;
    Graph<ll, ll> g(N);
    
    for (int i = 0; i < M; i++) {
        int a, b;
        cin >> a >> b;
        g.add_edge(a, Edge<ll>(a, b, 1));
    }
    
    ll K = std::numeric_limits<ll>::max();
    vector<Edge<ll>> route;
    vector<bool> checked(N+1);
    for (int i = 1; i <= N; i++) {
        if (checked[i]) {
            continue;
        }
        auto res = g.bfs(i, K);
        //cerr << res.first[i] << endl;
        if (res.first[i] == 0) {
            //このノードからつながる先にループはない うまくいかない
            for (auto r: res.second) {
                for (auto e: r) {
                    //checked[e.to] = true;
                }
            }
        } else if (res.first[i] == -1) {
            continue;
        } else if (K > res.first[i]) {
            K = res.first[i];
            route = res.second[i];
        }
        if (route.size() > 2) {
            bool ok = true;
            std::multiset<int> s;
            for (auto e: route) {
                s.insert(e.from);
            }
            for (auto n: s) {
                int cnt = 0;
                for (auto e: g.g[n]) {
                    cnt += s.count(e.to);
                }
                if (cnt >= 2) {
                    ok = false;
                    break;
                }
            }
            if (ok) {
                break;
            }
        }
    }
    
    if (K == std::numeric_limits<ll>::max()) {
        cout << -1 << endl;
        return 0;
    }
    cout << K << endl;
    for (auto e: route) {
        cout << e.from << endl;
    }
    
    return 0;
}


Measured memory_bytes: 16128