#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <string.h>
#include <fstream>
#include <cassert>
using namespace std;

#define sz(a) int((a).size())
#define rep(i, s, n)  for(int i = s; i <= (n); ++i)
#define rev(i, n, s)  for(int i = (n); i >= s; --i)
#define fore(x, a) for(auto &&x : a)
typedef long long ll;
const int mod = 1000000007;
const int N = 1005;

vector<int> g[N];
int d[N][N];

void go(int x, int p, int c, int _depth) {
  d[c][_depth]++;
  fore(y, g[x]) {
    if (y == p) continue;
    go(y, x, c, _depth + 1);
  }
}

class TreeDiameters {
public:
  int getMax( vector <int> p ) {
    int ans = 0;
    int n = sz(p) + 1;
    rep(i, 0, n - 1) {
      g[i].clear();
    }
    rep(i, 0, n - 2) {
      g[p[i]].push_back(i + 1);
      g[i + 1].push_back(p[i]);
    }
    rep(i, 0, n - 1) {
      int m = sz(g[i]) - 1;
      rep(j, 0, m) {
        memset(d[j], 0, sizeof(d[j]));
      }
      rep(j, 0, m) {
        go(g[i][j], i, j, 0);
      }
      rep(j, 0, n - 1) {
        int tot = 0;
        rep(k, 0, m) {
          tot += d[k][j];
        }
        if (tot == 0) break;
        int cur = 0;
        rep(k, 0, m) {
          cur += d[k][j] * (tot - d[k][j]);
        }
        ans = max(ans, cur/2);
      }
    }
    rep(i, 0, n - 2) {
      rep(j, 0, 1) memset(d[j], 0, sizeof(d[j]));
      go(i + 1, p[i], 0, 0);
      go(p[i], i + 1, 1, 0);
      rep(j, 0, n - 1) {
        if (d[0][j] == 0 && d[1][j] == 0) break;
        ans = max(ans, d[0][j] * d[1][j]);
      }
    }
    return ans;
  }
};