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 (GCC 5.4.1) (judge verdict: Accepted)

/// by ztx
/// blog.csdn.net/hzoi_ztx
#include <bits/stdc++.h>
#define Rep(i,l,r) for(i=(l);i<=(r);i++)
#define rep(i,l,r) for(i=(l);i< (r);i++)
#define Rev(i,r,l) for(i=(r);i>=(l);i--)
#define rev(i,r,l) for(i=(r);i> (l);i--)
#define Each(i,v)  for(i=v.begin();i!=v.end();i++)
#define r(x)   read(x)
typedef long long ll ;
typedef double lf ;
int CH , NEG ;
template <typename TP>inline void read(TP& ret) {
    ret = NEG = 0 ; while (CH=getchar() , CH<'!') ;
    if (CH == '-') NEG = true , CH = getchar() ;
    while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ;
    if (NEG) ret = -ret ;
}

#define  kN  200010LL
#define  t(p) e[0][p]
#define  n(p) e[1][p]
#define  s(u) st[u]

using namespace std;

int e[2][kN], st[kN], te = 0;
inline void Add(int u,int v) { te++;t(te)=v;n(te)=s(u);s(u)=te; }

int n, ind[kN], a[kN], nxt[kN];

int s[kN], top = 0;
set<int>S[kN];

void getnxt(int u) {
	if (nxt[u]) return;
	for(int p=s(u);p;p=n(p)) if (ind[t(p)]) {
		getnxt(nxt[u]=t(p)); break;
	}
}

bool check(int u,int U,int af,int aU) {
	int szorg, sznow, au, ret = true;
	szorg = S[u].size();
	S[u].insert(af);
	sznow = S[u].size();
	auto it = S[u].end(); it -- ;
	if (*it == S[u].size()-1) au = S[u].size();
	else {
		au = -1;
		for (auto v : S[u]) if (au ++ , au != v) break;
	}
	if (u==U && au!=aU) ret = false;
	if (ret==false || u==U) {
		if (sznow > szorg) S[u].erase(af);
		return ret;
	}
	ret = check(nxt[u],U,au,aU);
	if (sznow > szorg) S[u].erase(af);
	return ret;
}

int main() {
	int u, v, p, cnt;
    r(n);
    Rep (u,1,n) r(v), Add(u,v), ind[v] ++ ;
    Rep (u,1,n) if (!ind[u]) s[++top] = u;
    while (top) {
        u = s[top--];
        if (S[u].empty()) a[u] = 0;
        else {
            auto it = S[u].end(); it -- ;
            if (*it == S[u].size()-1) a[u] = S[u].size();
            else {
            	p = -1;
            	for (auto v : S[u]) if (p ++ , v != p) {
					a[u] = p; break;
				}
			}
        }
        for (p = s(u); p; p = n(p))
			if (S[t(p)].insert(a[u]), !(--ind[t(p)]))
				s[++top] = t(p);
    }
    cnt = 0;
    Rep (u,1,n) if (ind[u]) {
    	cnt ++ ;
    	if (S[u].empty()) continue;
    	getnxt(u);
    	auto it = S[u].end(); it -- ;
    	int val[3]; val[0] = 0;
    	p = -1;
    	for (auto v : S[u]) if (p ++ , v != p) {
    		while (p != v) {
    			val[++val[0]] = p;
    			p ++ ;
    			if (val[0] == 2) break;
			}
    		if (val[0] == 2) break;
		}
    	if (!val[0])
    		val[1] = S[u].size(), val[2] = val[1]+1;
		else if (val[0]==1)
			val[2] = S[u].size()+1;
		puts((check(nxt[u],u,val[1],val[1])||check(nxt[u],u,val[2],val[2])) ? "POSSIBLE": "IMPOSSIBLE");
		goto END;
    }
	puts(cnt&1 ? "IMPOSSIBLE": "POSSIBLE");
    END: getchar(), getchar();
    return 0;
}