Problem:
Score : 800 points

Problem Statement

There is a directed graph with N vertices and N edges. The vertices are numbered 1, 2, ..., N.

The graph has the following N edges: (p_1, 1), (p_2, 2), ..., (p_N, N), and the graph is weakly connected. Here, an edge from Vertex u to Vertex v is denoted by (u, v), and a weakly connected graph is a graph which would be connected if each edge was bidirectional.

We would like to assign a value to each of the vertices in this graph so that the following conditions are satisfied. Here, a_i is the value assigned to Vertex i.

Each a_i is a non-negative integer.

For each edge (i, j), a_i \neq a_j holds.

For each i and each integer x(0 ≤ x < a_i), there exists a vertex j such that the edge (i, j) exists and x = a_j holds.

Determine whether there exists such an assignment.

Constraints

2 ≤ N ≤ 200 000

1 ≤ p_i ≤ N

p_i \neq i

The graph is weakly connected.

Input

Input is given from Standard Input in the following format:

N
p_1 p_2 ... p_N

Output

If the assignment is possible, print POSSIBLE; otherwise, print IMPOSSIBLE.

Sample Input 1

4
2 3 4 1

Sample Output 1

POSSIBLE

The assignment is possible: {a_i} = {0, 1, 0, 1} or {a_i} = {1, 0, 1, 0}.

Sample Input 2

3
2 3 1

Sample Output 2

IMPOSSIBLE

Sample Input 3

4
2 3 1 1

Sample Output 3

POSSIBLE

The assignment is possible: {a_i} = {2, 0, 1, 0}.

Sample Input 4

6
4 5 6 5 6 4

Sample Output 4

IMPOSSIBLE

Solution in Rust (1.42.0) (judge verdict: Accepted)

use proconio::input;
// dbg {{{
#[allow(dead_code)]
mod dbg {
    use std::fmt::{Debug, Formatter};

    #[derive(Clone)]
    pub struct Tabular<'a, T: Debug>(pub &'a [Vec<T>]);
    impl<'a, T: Debug> Debug for Tabular<'a, T> {
        fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
            for i in 0..self.0.len() {
                writeln!(f, "{:2} | {:?}", i, &self.0[i])?;
            }
            Ok(())
        }
    }

    #[derive(Clone)]
    pub struct BooleanTable<'a>(pub &'a [Vec<bool>]);
    impl<'a> Debug for BooleanTable<'a> {
        fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
            for i in 0..self.0.len() {
                writeln!(f, "{:2} | {:?}", i, BooleanSlice(&self.0[i]))?;
            }
            Ok(())
        }
    }

    #[derive(Clone)]
    pub struct BooleanSlice<'a>(pub &'a [bool]);
    impl<'a> Debug for BooleanSlice<'a> {
        fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
            write!(
                f,
                "{}",
                self.0
                    .iter()
                    .map(|&b| if b { '#' } else { '.' })
                    .collect::<String>()
            )?;
            Ok(())
        }
    }
}
// }}}

fn mex(a: &[usize]) -> usize {
    let mut g = vec![false; a.len() + 1];
    for &x in a {
        if x <= a.len() {
            g[x] = true;
        }
    }
    (0..=a.len()).find(|&i| !g[i]).unwrap()
}

fn double_mex(a: &[usize]) -> (usize, usize) {
    let mut g = vec![false; a.len() + 2];
    for &x in a {
        if x <= a.len() + 1 {
            g[x] = true;
        }
    }
    let i0 = (0..=a.len()).find(|&i| !g[i]).unwrap();
    let i1 = (i0 + 1..=a.len() + 1).find(|&i| !g[i]).unwrap();
    (i0, i1)
}

fn main() {
    input!(n: usize, prt: [proconio::marker::Usize1; n]);
    let cycle: Vec<usize> = {
        let mut ckd = vec![false; n];
        let mut seq = vec![0];
        loop {
            let p = prt[*seq.last().unwrap()];
            seq.push(p);
            if ckd[p] {
                let s = (0..seq.len() - 1).find(|&s| seq[s] == p).unwrap();
                break seq[s..].iter().copied().rev().collect();
            }
            ckd[p] = true;
        }
    };

    let mut belongs_to_cycle = vec![false; n];
    cycle.iter().for_each(|&x| belongs_to_cycle[x] = true);

    let mut g = vec![vec![]; n];
    for (x, p) in prt.iter().copied().enumerate() {
        g[p].push(x);
    }

    fn dfs(x: usize, g: &[Vec<usize>]) -> usize {
        mex(g[x]
            .iter()
            .map(|&y| dfs(y, g))
            .collect::<Vec<_>>()
            .as_slice())
    }

    let cycle = cycle
        .iter()
        .map(|&root| {
            double_mex(
                g[root]
                    .iter()
                    .copied()
                    .filter(|&subroot| !belongs_to_cycle[subroot])
                    .map(|subroot| dfs(subroot, &g))
                    .collect::<Vec<_>>()
                    .as_slice(),
            )
        })
        .collect::<Vec<_>>();

    let &(s0, s1) = cycle.first().unwrap();
    for &s in &[s0, s1] {
        let mut g = s;
        for &(g0, g1) in cycle.iter().skip(1) {
            g = if g == g0 { g1 } else { g0 };
        }
        if g == s {
            println!("POSSIBLE");
            std::process::exit(0);
        }
    }
    println!("IMPOSSIBLE");
}