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)

#include<iostream>
#include<algorithm>
#include<vector>
#include<cassert>
#include<set>
#include<string>
using namespace std;

#define sz(x) (int)(x.size())
#define fr(i,a,b) for(int i=a;i<b;++i)
#define fdr(i,a,b) for(int i=b-1;i>=a;--i)
#define pb push_back
/////////////////

int const N = 2e5 + 41;
string const yes = "POSSIBLE";
string const no = "IMPOSSIBLE";

int n, m, a[N];
vector<int> e[N];
int order[N], cnt;
vector<int> c;
bool cyc[N];
int d[N];

void print(string s){
	cout << s << endl;
	exit(0);
}

int w[N];

void clearW(){
	fr(i, 0, N) w[i] = 0;
}

vector<int> st;

void findCyc(int u){
	st.pb(u);
	w[u] = 1;

	fr(i, 0, sz(e[u])){
		int to = e[u][i];
		if(!w[to]) findCyc(to);
		else{
			if(w[to] == 1){
				while(true){
					int v = st.back();
					st.pop_back();
					c.pb(v);
					if(v == to) break;
				}
			}
		}
	}

	w[u] = 2;
	if(sz(st) > 0 && st.back() == u) st.pop_back();
}

void dfs(int u){
	w[u] = 1;
	fr(i, 0, sz(e[u])){
		int to = e[u][i];
		if(w[to]) continue;
		dfs(to);
	}
	order[n-1-cnt] = u;
	++cnt;
}

int dfs1(int u){
	vector<int> v;
	fr(i, 0, sz(e[u])){
		int to = e[u][i];
		if(cyc[u] && cyc[to]) continue;
		assert(!w[to]);
		v.pb(dfs1(to));
	}
	sort(v.begin(), v.end());
	int cur = sz(v);
	fr(i, 0, sz(v)){
		if(i == 0 && v[i] != 0){
			cur = 0;
			break;
		}
		if(i != 0 && v[i] - v[i-1] > 1){
			cur = v[i-1] + 1;
			break;
		}
	}
	return d[u] = cur;
}

bool check(){
	fr(i, 0, n){
		set<int> q;
		fr(j, 0, sz(e[i])){
			int to = e[i][j];
			q.insert(d[to]);
		}
		if(q.find(d[i]) != q.end()) return false;
		fr(j, 0, d[i]) if(q.find(j) == q.end()) return false;
	}
	return true;
}

int getFirst(int id){
	set<int> q;
	fr(i, 0, sz(e[id])){
		int to = e[id][i];
		q.insert(d[to]);
	}
	fr(i, 0, N){
		if(q.find(i) == q.end()) return i;
	}
	assert(false);
	return 41;
}

int getSecond(int id){
	int cnt = 0;
	set<int> q;
	fr(i, 0, sz(e[id])){
		int to = e[id][i];
		if(cyc[to]) continue;
		q.insert(d[to]);
	}
	fr(i, 0, N){
		if(q.find(i) == q.end()){
			++cnt;
			if(cnt == 2) return i;
		}
	}

	assert(false);
	return 41;
}

void solve(){
	cin >> n;
	fr(i, 0, n){
		int pi;
		cin >> pi;
		--pi;
		e[pi].pb(i);
	}

	clearW();
	fr(i, 0, n) if(!w[i]) findCyc(i);
	fr(i, 0, sz(c)) cyc[c[i]] = true;

	clearW();
	fr(i, 0, n) if(!w[i]) dfs(i);

	clearW();
	fr(i, 0, n) if(!w[order[i]]) dfs1(order[i]);

	fr(i, 1, sz(c)){
		d[c[i]] = getFirst(c[i]);
	}
	if(check()) print(yes);

	d[c[0]] = getSecond(c[0]);
	fr(i, 1, sz(c)){
		d[c[i]] = getFirst(c[i]);
	}
	if(check()) print(yes);
	else print(no);

}

int main(){
#ifdef _DEBUG
	freopen("input.txt","r",stdin);
	freopen("output.txt","w",stdout);
#endif
	
	solve();

	return 0;
}