// Original C++ solution (slower):
#include <cstdio>

#include <iostream>

#include <algorithm>

#include <cmath>

#include <queue>

#include <cstdlib>

#include <cstring>

#include <vector>

#include <set>

#include <map>

using namespace std;

#define ll long long

#define maxn 100005

vector<int> tree[maxn];

vector<int> query[maxn];

int father[maxn];

int depth[maxn];

ll ans = 0;

int findSet(int x)//路径??

{

	if (x == father[x])

		return x;

	else

		return father[x] = findSet(father[x]);

}

void unionSet(int x, int y)//把y并到x中去

{

	int fx = findSet(x);

	int fy = findSet(y);

	if (fy == fx)

		return;

	father[fy] = fx;

}

void bfs()

{

	queue<int> Q;

	Q.push(1);

	int last = 0;

	int t;

	while (!Q.empty())

	{

		t = Q.front();

		if (last != 0)

		{

			query[last].push_back(t);

		}

		last = t;

		Q.pop();

		for (unsigned int i = 0; i < tree[t].size(); ++i)

		{

			Q.push(tree[t][i]);

		}

	}

}

void Tarjan_LCA(int u)

{

	father[u] = u;

	int t;

	for (unsigned int i = 0; i < tree[u].size(); ++i)

	{

		t = tree[u][i];

		depth[t] = depth[u] + 1;

		Tarjan_LCA(t);

		unionSet(u, t);

	}

	for (unsigned int i = 0; i < query[u].size(); ++i)

	{

		t = query[u][i];

		if (father[t] != 0)

		{

			//printf("sum %d %d\n", u, t);

			ans += (ll)depth[u] + (ll)depth[t] - 2 * (ll)depth[findSet(t)];

		}

		else

		{

			query[t].push_back(u);

		}

	}

}

int main()

{

	//freopen("input.txt", "r", stdin);

	//freopen("output.txt", "w", stdout);

	int n;

	scanf("%d", &n);

	int tmp;

	for (int i = 2; i <= n; ++i)

	{

		scanf("%d", &tmp);

		tree[tmp].push_back(i);

	}

	bfs();

	/*for (int i = 1; i <= n; ++i)

	{

		for (unsigned int j = 0; j < query[i].size(); ++j)

			printf("%d ", query[i][j]);

		printf("\n");

	}*/

	Tarjan_LCA(1);

	/*for (int i = 1; i <= n; ++i)

		printf("%d ", depth[i]);

	printf("\n");*/

	printf("%lld\n", ans);

	//system("pause");

	//while (1);

	return 0;

}

// Optimized solution to the same problem (faster):
#include<cstdio>

#include<vector>

#include<queue>

#include<algorithm>

using namespace std;



typedef long long LL;

const int MaxN=1e5+10;

int rmq[MaxN][20];

int dis[MaxN];

vector<int> mp[MaxN];

int n;



void dfs(int u,int pre){

	dis[u]=dis[pre]+1;

	if(pre)	rmq[u][0]=pre;

	else rmq[u][0]=u;

	for(int i=1;i<20;i++)

		if(u==1)	rmq[u][i]=u;

		else rmq[u][i]=rmq[rmq[u][i-1]][i-1];

	sort(mp[u].begin(),mp[u].end());

	for(int v:mp[u])

		dfs(v,u);

	}



queue<int> q;

vector<int> path;



void bfs(int u){

	q.push(u);

	while(!q.empty()){

		u=q.front();

		q.pop();

		for(int v:mp[u]){

			path.push_back(v);

			q.push(v);

			}

		}

	}



int getlca(int u,int v){

	if(dis[u]<dis[v])	swap(u,v);

	for(int i=19;i>=0;i--)

		if(dis[rmq[u][i]]>=dis[v])	u=rmq[u][i];

	if(u==v)	return u;

	for(int i=19;i>=0;i--){

		if(rmq[u][i]!=rmq[v][i]){

			u=rmq[u][i];

			v=rmq[v][i];

			}

		}

	return rmq[u][0];

	}



int main(){

	int p,u;

	scanf("%d",&n);

	for(int i=2;i<=n;i++){

		scanf("%d",&p);

		mp[p].push_back(i);

		}

	dfs(1,0);

	bfs(1);

	u=1;

	LL res=0;

	for(int v:path){

		res+=dis[u]+dis[v]-dis[getlca(u,v)]*2;

		u=v;

		}

	printf("%lld\n",res);

	return 0;

	}

// Fastest known solution for this problem: