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 C++14 (Clang 3.8.0) (judge verdict: Accepted)

#include <algorithm>
#include <cassert>
#include <cfloat>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <deque>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
 
#define FOR(i,k,n) for (int (i)=(k); (i)<(n); ++(i))
#define rep(i,n) FOR(i,0,n)
#define all(v) begin(v), end(v)
#define debug(x) cerr<< #x <<": "<<x<<endl
#define debug2(x,y) cerr<< #x <<": "<< x <<", "<< #y <<": "<< y <<endl
 
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<vector<int> > vvi;
typedef vector<ll> vll;
typedef vector<vector<ll> > vvll;
typedef deque<bool> db;
template<class T> using vv=vector<vector< T > >;

// cout vector
template<typename T> ostream& operator<<(ostream& s, const vector<T>& v) {
  int len = v.size(); s << "\n";
  for (int i = 0; i < len; ++i) {
    s << v[i]; if (i < len - 1) s << "\t";
  }
  s << "\n"; return s;
}

// cout deque
template<typename T> ostream& operator<<(ostream& s, const deque<T>& v) {
  int len = v.size(); s << "\n";
  for (int i = 0; i < len; ++i) {
    s << v[i]; if (i < len - 1) s << "\t";
  }
  s << "\n"; return s;
}

// cout 2-dimentional vector
template<typename T> ostream& operator<<(ostream& s, const vector< vector<T> >& vv) {
  int len = vv.size();
  for (int i = 0; i < len; ++i) { s << vv[i]; }
  return s;
}

vvi g;

deque<int> loop;

int dfs(int u) {
  if ((int)g.size() == 0) {
    return 0;
  }
  vi lis;
  for (int v : g[u]) {
    lis.push_back(dfs(v));
  }
  sort(all(lis));
  lis.erase(unique(all(lis)), end(lis));
  int lsz = lis.size();
  rep (i, lsz) {
    if (lis[i] != i) {
      return i;
    }
  }
  return lsz;
}

int main() {
  int n;
  scanf("%d", &n);
  g.resize(n);
  vi p(n);
  rep (i, n) {
    scanf("%d", &p[i]);
    p[i] -= 1;
    g[p[i]].push_back(i);
  }
  set<int> loop_s;
  for (int i = 0; ; i = p[i]) {
    if (loop_s.find(i) != end(loop_s)) {
      loop.push_back(i);
      break;
    }
    loop_s.insert(i);
  }
  while (true) {
    int nex = p[loop.back()];
    if (nex == loop[0]) {
      break;
    }
    loop.push_back(nex);
  }
  int m = loop.size();
  loop.push_back(loop[0]);
  vi grundy(n, -1);

  FOR (i, 1, m+1) {
    for (int u : g[loop[i]]) {
      if (u == loop[i-1]) {
        continue;
      }
      grundy[u] = dfs(u);
    }
  }

  vi cand = {0, 1};
  vi not_cand;
  for (int u : g[loop[0]]) {
    if (u == loop[1]) {
      continue;
    }
    not_cand.push_back(grundy[u]);
  }
  sort(all(not_cand));
  for (int gn : not_cand) {
    if (gn == cand[0]) {
      cand[0] = cand[1];
      cand[1] += 1;
    } else if (gn == cand[1]) {
      cand[1] += 1;
    }
  }

  vi grundy_loop;
  bool ans = false;
  rep (j, 2) {
    grundy_loop.assign(m+1, -1);
    grundy_loop[0] = cand[j];
    FOR (i, 1, m+1) {
      vi ng;
      for (int u : g[loop[i]]) {
        if (u == loop[i-1]) {
          ng.push_back(grundy_loop[i-1]);
        } else {
          ng.push_back(grundy[u]);
        }
      }
      sort(all(ng));
      ng.erase(unique(all(ng)), end(ng));
      ng.push_back(INT_MAX);
      int ngsz = ng.size();
      rep (k, ngsz) {
        if (ng[k] != k) {
          grundy_loop[i] = k;
          break;
        }
      }
    }
    if (grundy_loop[m] == grundy_loop[0]) {
      ans = true;
      break;
    }
  }
  if (ans) {
    printf("POSSIBLE\n");
  } else {
    printf("IMPOSSIBLE\n");
  }

  return 0;
}