#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <deque>
#include <functional>
#include <iomanip>
#include <locale>
#include <iostream>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#define REP(i,n) for(int i=0;i<(int)(n);i++)
#define ALL(x) (x).begin(),(x).end()

using namespace std;

using ll = long long;
using ld = long double;

template <typename T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template <typename T> T &chmax(T &a, const T &b) { return a = max(a, b); }
template <typename T> int len(const T &x) { return x.size(); }

template<typename T>
vector<T> table(int n, T v) { return vector<T>(n, v); }

template <class... Args>
auto table(int n, Args... args) {
  auto val = table(args...);
  return vector<decltype(val)>(n, move(val));
}

struct yes_no : numpunct<char> {
  string_type do_truename()  const { return "POSSIBLE"; }
  string_type do_falsename() const { return "IMPOSSIBLE"; }
};

struct Edge {
  int to;
  Edge(int t) : to(t) {}
};

using Graph = vector<vector<Edge>>;

void add_edge(Graph &g, int from, int to) {
  g[from].push_back(to);
  g[to].push_back(from);
}

class Namori {
  const int n;
  const Graph g;
  Graph tree_;
  set<int> roots_;
  void bfs() {
    vector<int> d(n);
    queue<int> que;
    REP(i,n) {
      d[i] = g[i].size();
      if (d[i] == 1) que.push(i);
    }
    while (!que.empty()) {
      int v = que.front();
      que.pop();
      for (Edge e: g[v]) {
        if (d[e.to] == 0) continue;
        assert (d[e.to] != 1);
        --d[v]; --d[e.to];
        tree_[e.to].push_back(Edge(v));
        if (d[e.to] == 1) que.push(e.to);
      }
    }
    REP(i,n) {
      if (d[i] == 2) roots_.insert(i);
      else assert(d[i] == 0);
    }
  }
public:
  Namori (const Graph &g_) : n(g_.size()), g(g_), tree_(n) { bfs(); }
  const Graph& tree() const { return tree_; }
  const set<int>& roots() const { return roots_; }
};

int nim(vector<int> v) {
  sort(ALL(v));
  auto it = unique(ALL(v));
  v.erase(it, end(v));
  REP(i,v.size()) if (v[i] != i) return i;
  return v.size();
}

vector<int> dfs(const Graph &g, int v) {
  vector<int> res;
  for (Edge e: g[v]) {
    res.push_back(nim(dfs(g, e.to)));
  }
  return res;
}

pair<int,int> get_nimval(vector<int> v) {
  int a = nim(v);
  v.push_back(a);
  sort(ALL(v));
  int b = nim(v);
  return make_pair(a, b);
}

bool is_ok(const vector<pair<int,int>> &nimval, const int back) {
  int x = back;
  for (auto &p: nimval)
    x = (x == p.first ? p.second : p.first);
  return x == back;
}

void solve(ll N, vector<ll> p) {
  for (ll &i: p) --i;
  Graph g(N);
  REP(i,N) add_edge(g, i, p[i]);
  Namori namori(g);
  int r = *namori.roots().begin();
  vector<int> roots;
  REP(i,namori.roots().size()) {
    roots.push_back(r);
    r = p[r];
  }
  reverse(ALL(roots));
  vector<pair<int,int>> nimval;
  for (int i: roots) {
    dfs(namori.tree(), i);
    nimval.push_back(get_nimval(dfs(namori.tree(), i)));
  }
  auto back = nimval.back();
  cout << (is_ok(nimval, back.first) || is_ok(nimval, back.second)) << endl;
}

int main() {
  locale loc(locale(), new yes_no);
  cout << boolalpha << setprecision(12) << fixed;
  cout.imbue(loc);
	ll N;
	scanf("%lld", &N);
	vector<ll> p(N-1+1);
	for (int i = 0 ; i <= N-1 ; i++) {
	  scanf("%lld", &p[i]);
	}
	solve(N, p);
	return 0;
}


Measured memory_bytes: 41728