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: Wrong Answer)

// #includes {{{
#include <bits/stdc++.h>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)(n);++i)
#define RREP(i,a,b) for(int i=(int)(a);i<(int)(b);++i)
#define FOR(i,c) for(__typeof((c).begin()) i=(c).begin();i!=(c).end();++i)
#define LET(x,a) __typeof(a) x(a)
//#define IFOR(i,it,c) for(__typeof((c).begin())it=(c).begin();it!=(c).end();++it,++i)
#define ALL(c) (c).begin(), (c).end()
#define MP make_pair

#define EXIST(e,s) ((s).find(e)!=(s).end())

#define RESET(a) memset((a),0,sizeof(a))
#define SET(a) memset((a),-1,sizeof(a))
#define PB push_back
#define DEC(it,command) __typeof(command) it=command

//debug
#define dump(x)  cerr << #x << " = " << (x) << endl;
#define debug(x) cerr << #x << " = " << (x) << " (L" << __LINE__ << ")" << " " << __FILE__ << endl;
#define debug2(x) cerr << #x << " = [";REP(__ind,(x).size()){cerr << (x)[__ind] << ", ";}cerr << "] (L" << __LINE__ << ")" << endl;

const int INF=0x3f3f3f3f;

typedef pair<int,int> pii;

/*
#ifdef MYDEBUG
#include"debug.h"
#include"print.h"
#endif
*/
// }}}

//{{{ Graph
typedef int Weight;
struct Edge {
	int src, dst, rev;
	Weight weight;
	Edge(int src, int dst, Weight weight=1,int rev=-1) :
		src(src), dst(dst), weight(weight), rev(rev) { }
};
bool operator < (const Edge &e, const Edge &f) {
	return e.weight != f.weight ? e.weight > f.weight : // !!INVERSE!!
		e.src != f.src ? e.src < f.src : e.dst < f.dst;
}
typedef vector<Edge> Edges;
//typedef vector<Edges> Graph;

typedef vector<Weight> Array;
typedef vector<Array> Matrix;

struct Graph:vector<Edges>{
	Graph(){}
	Graph(const int &n){this->assign(n,Edges());}
	//add bi-directional edge
	void addBiEdge(int from ,int to, Weight w=1){
		while(this->size()<max(from,to)+1)this->push_back(Edges());
		this->at(from).push_back(Edge(from,to,w,this->at(to).size()));
		this->at(to).push_back(Edge(to,from,w,this->at(from).size()-1));
	}
	//add directional edge
	void addEdge(int from ,int to, Weight w=1){
		while(this->size()<from+1)this->push_back(Edges());
		this->at(from).push_back(Edge(from,to,w));
	}
};
#ifdef DEBUG
#include"graph/graphviz.h"
#endif
//}}}

//{{{ Print functions
// Input/Output
template<class T>
void matrix_out(const vector<vector<T> > &x){
	REP(i,x.size()){
		REP(j,x[0].size()){
			cout<<x[i][j]<<"\t";
		}
		cout<<endl;
	}
}

template<class U,class S,class T>
U &operator<<(U &os, const pair<S,T> &p){
	os<<"("<<p.first<<","<<p.second<<")";
	return os;
}

template<class U,class T>
U &operator<<(U &os, const vector<T> &x) {
	os<<"vector[";
	REP(i,x.size()){
		os<<x[i];
		if(i!=x.size()-1)os<<",";
	}
	os<<"]";
	return os;
}

template<class U,class T>
U &operator<<(U &os, const deque<T> &x) {
	os<<"deque[";
	REP(i,x.size()){
		os<<x[i];
		if(i!=x.size()-1)os<<",";
	}
	os<<"]";
	return os;
}

template<class U,class T>
U &operator<<(U &os, const set<T> &x) {
	os<<"set[";
	FOR(it,x){
		os<<*it;
		if(++it!=x.end())os<<",";
		it--;
	}
	os<<"]";
	return os;
}

template<class U,class T>
U &operator<<(U &os, const list<T> &x) {
	os<<"list[";
	FOR(it,x){
		os<<*it;
		if(++it!=x.end())os<<",";
		it--;
	}
	os<<"]";
	return os;
}

template<class U,class T>
U &operator<<(U &os, const multiset<T> &x) {
	os<<"multiset[";
	FOR(it,x){
		os<<*it;
		if(++it!=x.end())os<<",";
		it--;
	}
	os<<"]";
	return os;
}



template<class U,class S,class T>
U &operator<<(U &os, const map<S,T> &x) {
	os<<"map[";
	FOR(it,x){
		os<<*it;
		if(++it!=x.end())os<<",";
		it--;
	}
	os<<"]";
	return os;
}

void printBit(int b,int k=-1){
	if(k==-1){
		int bb=1,i=0;
		while(bb){
			if(b&bb)k=i;
			bb<<=1;i++;
		}
	}
	REP(ct,k){
		cout<<b%2;
		b>>=1;
	}
	cout<<endl;
}

//}}}

//{{{ stronglyConnectedComponents(const Graph &g)
struct scc_t{
	vector<vector<int> > scc;
	vector<int> id;
};
void visit(const Graph &g, int v, scc_t &ret,
		stack<int> &S, vector<bool> &inS,
		vector<int> &low, vector<int> &num, int& time) {
	low[v] = num[v] = time;
	time++;
	S.push(v); inS[v] = true;
	for(const auto &e:g[v]){
		int w = e.dst;
		if (num[w] == -1) {
			visit(g, w, ret, S, inS, low, num, time);
			low[v] = min(low[v], low[w]);
		} else if (inS[w])
			low[v] = min(low[v], num[w]);
	}
	if (low[v] == num[v]) {
		ret.scc.push_back(vector<int>());
		while (1) {
			int w = S.top(); S.pop(); inS[w] = false;
			ret.scc.back().push_back(w);
			if (v == w) break;
		}
	}
}
scc_t stronglyConnectedComponents(const Graph& g) {
	const int n = g.size();
	scc_t ret{vector<vector<int> >(),vector<int>(n,-1)};
	vector<int> low(n,-1), num(n,-1);
	stack<int> S;
	vector<bool> inS(n);
	int time = 0;
	REP(u, n) if (num[u] == -1) visit(g, u, ret, S, inS, low, num, time);
	REP(i,ret.scc.size())REP(j,ret.scc[i].size())ret.id[ret.scc[i][j]] = i;
	return ret;
}
//}}}

Graph g;

vector<bool> vis;

vector<int> loop, rev_loop;
vector<int> nxt, rev_nxt;
vector<int> gr;

vector<int> stc;
void dfs0(int u){
	if(vis[u]){
		cerr<<stc<<endl;
		for(int i = (int)stc.size()-1;i>=0;i--){
			
			loop.push_back(stc[i]);
			if(stc[i] == u)break;
		}
		return;
	}
	stc.push_back(u);
	vis[u] = true;
	for(auto &&e:g[u]){
		dfs0(e.dst);
	}
	stc.pop_back();
}

int dfs1(int u, int p = -1){
	unordered_set<int> st;
	for(auto &&e:g[u]){
		if(nxt[u]!=-1 and e.dst==nxt[u])continue;
		st.insert(dfs1(e.dst,u));
	}
	for(int i=0;;i++){
		if(st.find(i)==st.end())return gr[u] = i;
	}
}

void solve(int N, vector<int> p){
	g.assign(N,Edges());
	REP(u,N)g.addEdge(p[u],u);
	auto s(stronglyConnectedComponents(g));
	unordered_set<int> cyc;
	REP(i,s.scc.size()){
		if(s.scc[i].size()>1){
			cyc.insert(ALL(s.scc[i]));
			break;
		}
	}
	assert(cyc.size()>0);
	/*
	vis.assign(N,false);
	REP(u,N){
		if(loop.size()==0)dfs0(u);
		else break;
	}
	*/
	gr.assign(N,-1);
	/*
	dump(loop.size());
	REP(i,loop.size()){
		cout<<loop[i]<<" ";
	}
	cout<<endl;
	rev_loop = loop;
	reverse(ALL(loop));
	*/
	nxt.assign(N,-1);
	rev_nxt.assign(N,-1);
	for(auto &&u:cyc){
		bool found = false;
		for(auto &&e:g[u]){
			if(EXIST(e.dst,cyc)){
				nxt[u] = e.dst;
				rev_nxt[e.dst] = u;
				found = true;
			}
		}
		assert(found);
	}
	int start = *cyc.begin();
	for(int u = start;;){
		loop.push_back(u);
		u = nxt[u];
		if(u==start)break;
	}
	rev_loop = loop;
	reverse(ALL(rev_loop));
	
	/*
	REP(i,loop.size()){
		nxt[loop[i]] = loop[(i+1)%loop.size()];
		rev_nxt[rev_loop[i]] = rev_loop[(i+1)%loop.size()];
	}
	*/
	REP(i,loop.size()){
		dfs1(loop[i]);
	}
	for(int t=0;t<=4;t++){
		/*
		dump(t);
		dump(rev_loop.size());
		dump(rev_loop[0]);
		*/
		gr[rev_loop[0]] = t;
		for(int i=1;i<rev_loop.size() + 1;i++){
			unordered_set<int> st;
			int u = rev_loop[i%rev_loop.size()];
//			dump(u);
			for(auto &e:g[u]){
				st.insert(gr[e.dst]);
			}
			for(int i=0;;i++){
				if(st.find(i)==st.end()){
					gr[u] = i;
					break;
				}
			}
		}
		if(gr[rev_loop[0]]==t){
			cout<<"POSSIBLE"<<endl;
			return;
		}
		/*
		int gr2;
		unordered_set<int> st;
		int u = rev_loop[0];
		for(auto &&e:g[u]){
			st.insert(gr[e.dst]);
		}
		for(int i=0;;i++){
			if(st.find(i)==st.end()){
				gr[u] = i;
				gr2 = i;
				break;
			}
		}
		if(gr[u]==gr2){
			return;
		}
		*/
	}
	cout<<"IMPOSSIBLE"<<endl;
}

int main(){	
	int N;
	scanf("%d",&N);
	vector<int> p(N-1+1);
	for(int i = 0 ; i <= N-1 ; i++){
		scanf("%d",&p[i]);
		p[i]--;
	}
	solve(N, p);
	return 0;
}