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 Rust (1.15.1) (judge verdict: Accepted)

#[allow(unused_imports)]
use std::cmp;
use std::io::Write;

// Input macro from https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8
macro_rules! input {
  (source = $s:expr, $($r:tt)*) => {
    let mut iter = $s.split_whitespace();
    input_inner!{iter, $($r)*}
  };
  ($($r:tt)*) => {
    let s = {
      use std::io::Read;
      let mut s = String::new();
      std::io::stdin().read_to_string(&mut s).unwrap();
      s
    };
    let mut iter = s.split_whitespace();
    input_inner!{iter, $($r)*}
  };
}

macro_rules! input_inner {
  ($iter:expr) => {};
  ($iter:expr, ) => {};

  ($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
    let $var = read_value!($iter, $t);
    input_inner!{$iter $($r)*}
  };
}

macro_rules! read_value {
  ($iter:expr, ( $($t:tt),* )) => {
    ( $(read_value!($iter, $t)),* )
  };

  ($iter:expr, [ $t:tt ; $len:expr ]) => {
    (0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
  };

  ($iter:expr, chars) => {
    read_value!($iter, String).chars().collect::<Vec<char>>()
  };

  ($iter:expr, usize1) => {
    read_value!($iter, usize) - 1
  };

  ($iter:expr, [ $t:tt ]) => {{
    let len = read_value!($iter, usize);
    (0..len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
  }};

  ($iter:expr, $t:ty) => {
    $iter.next().unwrap().parse::<$t>().expect("Parse error")
  };
}

#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy)]
enum State {
  Fresh,
  Temp,
  Fix,
}

fn find_cycle(v: usize, adj: &Vec<Vec<usize>>, prev: &mut Vec<Option<usize>>, state: &mut Vec<State>) -> Option<usize> {
  match state[v] {
    State::Fresh => {
      state[v] = State::Temp;
      for &next in &adj[v] {
        prev[next] = Some(v);
        if let Some(e) = find_cycle(next, adj, prev, state) {
          return Some(e);
        }
      }
      state[v] = State::Fix;
    }
    State::Temp => {
      return Some(v);
    }
    State::Fix => ()
  }
  None
}

fn main() {
  let out = std::io::stdout();
  let mut out = std::io::BufWriter::new(out.lock());
  macro_rules! puts {
    ($($format:tt)*) => (write!(out,$($format)*).unwrap());
  }
  input! {
    n: usize,
    m: usize,
    es: [(usize1, usize1); m],
  }
  let mut adj = vec![vec![]; n];
  for &(a, b) in &es {
    adj[a].push(b);
  }
  let mut prev = vec![None; n];
  let mut state = vec![State::Fresh; n];
  let mut end = None;
  for i in 0 .. n {
    if let Some(e) = find_cycle(i, &adj, &mut prev, &mut state) {
      end = Some(e);
      break;
    }
  }
  use std::collections::BTreeSet;
  match end {
    Some(end) => {
      let mut vs = BTreeSet::new();
      let mut v = end;
      loop {
        vs.insert(v);
        v = prev[v].unwrap();
        if v == end {
          break;
        }
      }
      let mut es = es;
      loop {
        es = es.into_iter().filter(|&(a, b)| vs.contains(&a) && vs.contains(&b)).collect();
        let rest: Vec<_> = es.iter().filter(|&&(a, b)| prev[b] != Some(a)).collect();
        match rest.first() {
          None => break,
          Some(&&(mut a, b)) => {
            prev[b] = Some(a);
            let mut next_vs = BTreeSet::new();
            next_vs.insert(a);
            while a != b {
              a = prev[a].unwrap();
              next_vs.insert(a);
            }
            vs = next_vs;
          }
        }
      }
      puts!("{}\n", vs.len());
      for &v in &vs {
        puts!("{}\n", v+1);
      }
    }
    None => {
      puts!("-1\n");
    }
  }
}