Problem:
Score : 600 points

Problem Statement

Given is a directed graph G with N vertices and M edges.

The vertices are numbered 1 to N, and the i-th edge is directed from Vertex A_i to Vertex B_i.

It is guaranteed that the graph contains no self-loops or multiple edges.

Determine whether there exists an induced subgraph (see Notes) of G such that the in-degree and out-degree of every vertex are both 1. If the answer is yes, show one such subgraph.

Here the null graph is not considered as a subgraph.

Notes

For a directed graph G = (V, E), we call a directed graph G' = (V', E') satisfying the following conditions an induced subgraph of G:

V' is a (non-empty) subset of V.

E' is the set of all the edges in E that have both endpoints in V'.

Constraints

1 \leq N \leq 1000

0 \leq M \leq 2000

1 \leq A_i,B_i \leq N

A_i \neq B_i

All pairs (A_i, B_i) are distinct.

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N M
A_1 B_1
A_2 B_2
:
A_M B_M

Output

If there is no induced subgraph of G that satisfies the condition, print -1.
Otherwise, print an induced subgraph of G that satisfies the condition, in the following format:

K
v_1
v_2
:
v_K

This represents the induced subgraph of G with K vertices whose vertex set is \{v_1, v_2, \ldots, v_K\}. (The order of v_1, v_2, \ldots, v_K does not matter.)
If there are multiple subgraphs of G that satisfy the condition, printing any of them is accepted.

Sample Input 1

4 5
1 2
2 3
2 4
4 1
4 3

Sample Output 1

3
1
2
4

The induced subgraph of G whose vertex set is \{1, 2, 4\} has the edge set \{(1, 2), (2, 4), (4, 1)\}. The in-degree and out-degree of every vertex in this graph are both 1.

Sample Input 2

4 5
1 2
2 3
2 4
1 4
4 3

Sample Output 2

-1

There is no induced subgraph of G that satisfies the condition.

Sample Input 3

6 9
1 2
2 3
3 4
4 5
5 6
5 1
5 2
6 1
6 2

Sample Output 3

4
2
3
4
5

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)


//Chaos///

#pragma GCC optimize("O3", "unroll-loops")
#pragma GCC target("avx2")
#include<bits/stdc++.h> 
#include <ext/pb_ds/assoc_container.hpp> 
#include <ext/pb_ds/tree_policy.hpp> 
using namespace __gnu_pbds; 
using namespace std;
#if DEBUG && !ONLINE_JUDGE
    #define debug(args...)     (Debugger()) , args
    class Debugger
    {
        public:
        Debugger(const std::string& _separator = ", ") :
        first(true), separator(_separator){}
        template<typename ObjectType>
        Debugger& operator , (const ObjectType& v)
        {
            if(!first)
                std::cerr << separator;
            std::cerr << v;
            first = false;
            return *this;
        }
        ~Debugger() {  std::cerr << endl;}
 
        private:
        bool first;
        std::string separator;
    };
    template <typename T1, typename T2>
    inline std::ostream& operator << (std::ostream& os, const std::pair<T1, T2>& p)
    {
        return os << "(" << p.first << ", " << p.second << ")";
    }
    template<typename T>
    inline std::ostream &operator << (std::ostream & os,const std::vector<T>& v)
    {
        bool first = true;
        os << "[";
        for(unsigned int i = 0; i < v.size(); i++)
        {
            if(!first)
                os << ", ";
            os << v[i];
            first = false;
        }
        return os << "]";
    }
    template<typename T>
    inline std::ostream &operator << (std::ostream & os,const std::set<T>& v)
    {
        bool first = true;
        os << "[";
        for (typename std::set<T>::const_iterator ii = v.begin(); ii != v.end(); ++ii)
        {
            if(!first)
                os << ", ";
            os << *ii;
            first = false;
        }
        return os << "]";
    }
    template<typename T1, typename T2>
    inline std::ostream &operator << (std::ostream & os,const std::map<T1, T2>& v)
    {
        bool first = true;
        os << "[";
        for (typename std::map<T1, T2>::const_iterator ii = v.begin(); ii != v.end(); ++ii)
        {
            if(!first)
                os << ", ";
            os << *ii ;
            first = false;
        }
        return os << "]";
    }
#else
    #define debug(args...)                 
#endif
const int mod = 1000000007;
// const int mod = 998244353;
#define ok order_of_key
#define fo find_by_order
#define ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update> 
#define ll long long
#define rep(i,a,b) for(int i=(a);i<(b);i++)
#define repp(i,n) for(int i=(0);i<(n);i++)
#define repr(i,n) for(int i=(n);i>=0;i--)
#define reprr(i,n) for(int i=(n);i>0;i--)
#define repl(i,a,b) for(ll i=(a);i<(b);i++)
#define newl cout<<'\n'
#define inf 1000000000
#define repaa(i,a) for(auto i=a.rbegin();i!=a.rend();++i)
#define pb push_back 
#define test cout<<"test"<<endl
#define tc int tt;cin>>tt;while(tt--)
#define start int tt;tt=read();while(tt--)
#define startk int tt;cin>>tt;for(int kk=1;kk<=tt;kk++)
#define mem(v,i) memset(v,i,sizeof(v))//Use mem(v,60) to initialize with 10^9
#define all(x) x.begin(), x.end()
#define inf1 1e18
#define repa(i,a) for (auto i : a)
#define X first
#define Y second
#define lb lower_bound
#define ub upper_bound
#define gcd(a,b)    __gcd((a),(b))
#define lcm(a,b)    ((a)*(b)) / gcd((a),(b))
#define in(a,n) repp(jjj,n)cin>>a[jjj];
#define re(a,n) repp(jjj,n)a[jjj]=read();
#define retree(a,m) repp(i,m){int tmp1=read()-1,tmp2=read()-1;a[tmp1].eb(tmp2);a[tmp2].eb(tmp1);}
#define intree(a,m) repp(i,m){int tmp1,tmp2;cin>>tmp1>>tmp2;tmp1--,tmp2--;a[tmp1].eb(tmp2);a[tmp2].eb(tmp1);}
#define ins insert
#define case(ans) cout << "Case #" << kk << ':' << ' ' << ans << nl
#define er erase
#define sz(a) (int)(a.size())
#define print(x,n,k) repp(i,n){repp(j,k)cout<<x[i][j]<<"  ";newl;} 
#define mt make_tuple
#define eb emplace_back
#define bpl(i) __builtin_popcountll(i)
#define bp(i) __builtin_popcount(i)
#define precision(x) cout << fixed << setprecision(x);
#define si set<int>
#define usi unordered_set<int>
#define sl set < ll >
#define usl unordered_set < ll >
#define sip set < ip >
#define sil set < il > 
#define mi map<int , int >
#define umi unordered_map<int , int >
#define ml map < ll , ll>
#define uml unordered_map < ll , ll>
#define mip map<ip , int>   
#define mmx(x1,x2) min(x1,x2) , max(x1,x2)
#define make_unique(x) sort(all((x))); (x).resize(unique(all((x))) - (x).begin())
#define mxe max_element
#define mne min_element
#define srt(v) sort(all(v))
#define rsrt(v) sort(v.rbegin(), v.rend())
#define yn {puts("YES");}else{puts("NO");}
typedef long double ld;
typedef vector<int> vi;
typedef vector<char> vc;
typedef vector<ll> vl;
typedef vector < vi > vii;
typedef vector<pair<int,int>> vip;
typedef vector<pair<ll,ll>> vil;
typedef vector < vl > vll;
typedef pair<int, int> ip;
typedef pair<ll, ll> il;
typedef tuple<int,int,int> state;
typedef tuple<ll,ll,ll> statel;
const int dx[4]={1,0,0,-1};
const int dy[4]={0,1,-1,0};
const int dxo[8] = {-1, -1, -1, 0, 1, 1, 1, 0};
const int dyo[8] = {-1, 0, 1, 1, 1, 0, -1, -1};
const double eps = 1e-10;
const char nl = '\n';
const char sp = ' ';
#ifdef Fading
#define gc getchar
#endif
#ifndef Fading
inline char gc(){static char now[1<<16],*S,*T;if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}return *S++;}
#endif
inline ll read(){register ll x=0,f=1;char ch=gc();while (!isdigit(ch)){if(ch=='-')f=-1;ch=gc();}while (isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=gc();}return (f==1)?x:-x;}
template<typename T>T Min(T v) {return v;}template<typename T, typename... Args>T Min(T first, Args... args) {return min(first , Min(args...));}
template<typename T>T Max(T v) {return v;}
template<typename T, typename... Args> T Max(T first, Args... args) {return max(first , Max(args...));}
template<typename T> T mult(T v) {return v;} template<typename T, typename... Args>T mult(T first, Args... args) {return mult((first%mod * mult(args...))%mod);}
template<class T , class U> inline bool remax(T &a, U b) { return a < b ? a = b, 1 : 0; }
template<class T , class U> inline bool remin(T &a, U b) { return a > b ? a = b, 1 : 0; }
template<class A, class B> void add(A &a, B b){a += b;if(a >= mod) a -= mod;if(a < 0) a += mod;}
template<class A, class B> ll addr(A a, B b){a += b;if(a >= mod) a -= mod;if(a < 0) a += mod;return a;}
template<class T1,class T2>T2 min(T1 a,T2 b){return min((T2)a,b);}
template<class T1,class T2>T2 max(T1 a,T2 b){return max((T2)a,b);}
template<class A> void pnt(A a[],int st,int en) {rep(i,st,en) cout << a[i] << ' ' ; newl;}
template<class A> void pnt(A a[],int en) {repp(i,en) cout << a[i] << ' ' ; newl;}
template<class A> void pnt(vector<A>&a, char tmp = '\n') {repa(i,a) cout << i << ' ' ; newl;}
template<class A> void pnt(A &a , char tmp = '\n') {cout << a << tmp;}
template<class A> void pnt(set<A>&a , char tmp = '\n') {repa(i,a) cout << i << ' ' ; newl;}
template<class A> void pnt(unordered_set<A>&a, char tmp = '\n') {repa(i,a) cout << i << ' ' ; newl;}
template<class A ,class B> void pnt(pair<A,B>&a, char tmp = '\n'){cout << a.X << ' ' << a.Y << tmp;}
template<typename T1,typename T2>inline istream& operator>>(istream&i,pair<T1,T2>&v){return i>>v.X>>v.Y;}
template<typename T , typename A>void W(T v ,A &c) {pnt(v,c);}template<typename T, typename A , typename... Args>void W(T first,A &c , Args... args) {pnt(first,c) ; W(args...);}
template <class T1>void kill(T1 ans){pnt(ans);exit(0);}

ll nc2(ll a){return a * (a - 1) / 2;}
ll setbit(ll num, ll kk){ return 1LL*(num|(1LL<<kk)); }
ll unsetbit(ll num, ll kk){ return 1LL*(num&~(1LL<<kk)); }
ll invertbit(ll num, ll kk){ return 1LL*(num^(1LL<<kk)); }
bool kthbit(ll num, ll kk){ return num&(1LL<<kk); }
bool matchpar(ll a, ll b){return (a&1) == (b&1);}
ll mceil(ll a, ll b){return a/b + (ll)(a%b > 0);}
ll poww(ll a, ll b,ll m = mod){ll val = 1;a %= m;while (b > 0){if (b & 1) val = (a * val) % m;a = (a * a) % m;b >>= 1;}return val;}
ll inv(ll a){return poww(a , mod - 2);}
ll gcdll(ll x, ll y){return y == 0 ? x : gcdll(y, x % y);}
int mylog(ll x , ll y){if(x == 0) return -1;return mylog(x/y,y) + 1;}

//-----------------------------------------------------end--------------------------------------//

class SCC{
    static const int N = 1005;
    public :
    vi a[N];
    int n;
    bool vis[N];
    vii SCCs;
    SCC(int n){mem(vis,0);this -> n = n;}

    void find_topo(vi &topo , int node){
        vis[node] = 1;
        repa(i,a[node]) if(!vis[i]) find_topo(topo,i);
        topo.eb(node);
    }   

    void dfs(vi &curSCC , int node){
        vis[node] = 1;
        curSCC.eb(node);
        repa(i,a[node]) if(!vis[i]) dfs(curSCC , i);
    }

    void find_scc(){
        vi topo;
        repp(i,n) if(!vis[i]) find_topo(topo , i);
        mem(vis , 0);
        repa(node , topo){
            vi tmp;
            if(!vis[node]) dfs(tmp,node) , SCCs.eb(tmp);
        }
    }

};

bool vis[1005] , check[1005];
int root;
bool fl;
vi v;

void dfs(vi (&a)[1005], int node , int prev = -1){
    vis[node] = 1;
    repa(i,a[node]) {
        if(i == root && check[i] == 0) {
            check[node] = check[i] = check[prev] = 1;
            v.eb(node);
            return ;
        }
        if(!vis[i]) dfs(a,i,node);
    }
    if(check[node]) v.eb(node) , check[prev == -1 ? 1004 : prev] = 1;
}

void solve(vi (&a)[1005]){
    umi mp;debug(root);
    int mn = inf , pos = - 1 , ch = 0;
    reverse(all(v));
    repa(i,v){
        repa(j,a[i]) if(mp.count(j)) if(remin(mn , ch - mp[j])) pos = mp[j];
        mp[i] = ch ++;
    }
    if(pos != -1){
        vi temp;
        rep(i,pos,pos + mn + 1) temp.eb(v[i]);
        v = temp;
    }
    int cur = 0;
    mp.clear();
    repp(i,v.size()) mp[v[i]] = i;
    vi ans;
    repp(i,v.size()){
        int mx = -1;
        ans.eb(v[i]);
        repa(j,a[v[i]]) remax(mx , mp[j]);
        if(mx > i) i = mx - 1;
    }
    W(ans.size() , nl);
    repa(i,ans) W(i + 1,nl);
    exit(0);
}

signed main()
{
    ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int n , m;
    cin >> n >> m;
    SCC gr(n);
    repp(i,m) {
        int tmp1 , tmp2;
        cin >> tmp1 >> tmp2;
        tmp1 -- , tmp2 --;
        gr.a[tmp1].eb(tmp2);
    } 
    gr.find_scc();
    repa(i,gr.SCCs) if(i.size() > 1) root = i[0] , dfs(gr.a,i[0]) , solve(gr.a);
    W(-1,nl);
}