use std::vec::Vec;
use std::collections::BinaryHeap;
use std::cmp::Ordering;
use std::cmp::Ordering::Greater;
use std::cmp::Ordering::Less;
use std::usize;
use std::ops::Add;
use std::fmt;

fn read<T: std::str::FromStr>() -> T {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim().parse().ok().unwrap()
}

fn read_vec<T: std::str::FromStr>() -> Vec<T> {
    read::<String>().split_whitespace().map(|e| e.parse().ok().unwrap()).collect()
}

fn main() {
    let n: usize = read();
    let mut a = vec![Vec::new(); n];
    for i in 0..n {
        let v: usize = read();
        a[i].push((v-1, 1));
    }

    match dijkstra_to_goal(&a, 0, 1) {
        Dist::Inf    => println!("-1"),
        Dist::Fin(d) => println!("{}", d),
    }

}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
enum Dist {
  Inf,
  Fin(usize)
}

impl Ord for Dist {
  fn cmp(&self, other: &Dist) -> Ordering {
    match (self, other) {
      (&Dist::Inf, _) => Greater,
      (_, &Dist::Inf) => Less,
      (&Dist::Fin(x), &Dist::Fin(y)) => x.cmp(&y),
    }
  }
}

impl PartialOrd for Dist {
    fn partial_cmp(&self, other: &Dist) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Add for Dist {
  type Output = Self;
  fn add(self, other: Self) -> Self {
    match (self, other) {
      (Dist::Inf, Dist::Inf) | (Dist::Inf, _) | (_, Dist::Inf) => Dist::Inf,
      (Dist::Fin(x), Dist::Fin(y)) => Dist::Fin(x + y),
    }
  }
}

impl fmt::Display for Dist {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    match self {
      &Dist::Inf    => write!(f, "Inf"),
      &Dist::Fin(x) => write!(f, "Fin({})", x),
    }
  }
}


// 単一始点から目的のノードへの最短経路超を探索
// 隣接リストによるグラフの表現
// (target, cost)
fn dijkstra_to_goal(adj_list: &Vec<Vec<(usize, usize)>>, start: usize, goal: usize) -> Dist {
  #[derive(Copy, Clone, Eq, PartialEq)]
  struct State {
      cost: Dist,
      position: usize,
  }

  impl Ord for State {
      fn cmp(&self, other: &State) -> Ordering {
        match other.cost.cmp(&self.cost) {
          Less    => Less,
          Greater => Greater,
          _       => self.position.cmp(&other.position),
        }
      }
  }

  impl PartialOrd for State {
      fn partial_cmp(&self, other: &State) -> Option<Ordering> {
          Some(self.cmp(other))
      }
  }

  // dist[node] = current shortest distance from `start` to `node`
  let mut dist: Vec<_> = (0..adj_list.len()).map(|_| Dist::Inf).collect();

  let mut heap = BinaryHeap::new();

  // We're at `start`, with a zero cost
  dist[start] = Dist::Fin(0);
  heap.push(State { cost: Dist::Fin(0), position: start });

  // Examine the frontier with lower cost nodes first (min-heap)
  while let Some(State { cost, position }) = heap.pop() {
      // Alternatively we could have continued to find all shortest paths
      if position == goal { return cost; }

      // Important as we may have already found a better way
      if cost > dist[position] { continue; }

      // For each node we can reach, see if we can find a way with
      // a lower cost going through this node
      for &(node, edge_cost) in &adj_list[position] {
          let next = State { cost: cost + Dist::Fin(edge_cost), position: node };

          // If so, add it to the frontier and continue
          if next.cost < dist[next.position] {
              heap.push(next);
              // Relaxation, we have now found a better way
              dist[next.position] = next.cost;
          }
      }
  }

  // Goal not reachable
  Dist::Inf
}


Measured memory_bytes: 16636