You are in charge of the BubbleReactor. It consists of N BubbleCores connected with N lines of electrical wiring. Each electrical wiring connects two distinct BubbleCores. There are no BubbleCores connected with more than one line of electrical wiring.

Your task is to start the BubbleReactor by starting each BubbleCore. In order for a BubbleCore to be started it needs to be receiving power from a directly connected BubbleCore which is already started. However, you can kick-start one BubbleCore manually without needing power. It is guaranteed that all BubbleCores can be started.

Before the BubbleCore boot up procedure its potential is calculated as the number of BubbleCores it can power on (the number of inactive BubbleCores which are connected to it directly or with any number of inactive BubbleCores in between, itself included)

Start the BubbleReactor so that the sum of all BubbleCores' potentials is maximum.

Input

First line contains one integer N (3 ≤ N ≤ 15.000), the number of BubbleCores.

The following N lines contain two integers U, V (0 ≤ U ≠ V < N) denoting that there exists electrical wiring between BubbleCores U and V.

Output

Single integer, the maximum sum of all BubbleCores' potentials.

Example

Input


10
0 1
0 3
0 4
0 9
1 2
2 3
2 7
4 5
4 6
7 8


Output


51

Note

If we start by kickstarting BubbleCup 8 and then turning on cores 7, 2, 1, 3, 0, 9, 4, 5, 6 in that order we get potentials 10 + 9 + 8 + 7 + 6 + 5 + 1 + 3 + 1 + 1 = 51
#include <bits/stdc++.h>
using namespace std;
inline char gc() {
  static const long long L = 233333;
  static char sxd[L], *sss = sxd, *ttt = sxd;
  if (sss == ttt) {
    ttt = (sss = sxd) + fread(sxd, 1, L, stdin);
    if (sss == ttt) {
      return EOF;
    }
  }
  return *sss++;
}
inline char readalpha() {
  char c = gc();
  for (; !isalpha(c); c = gc())
    ;
  return c;
}
inline char readchar() {
  char c = gc();
  for (; c == ' '; c = gc())
    ;
  return c;
}
template <class T>
inline bool read(T& x) {
  bool flg = false;
  char c = gc();
  x = 0;
  for (; !isdigit(c); c = gc()) {
    if (c == '-') {
      flg = true;
    } else if (c == EOF) {
      return false;
    }
  }
  for (; isdigit(c); c = gc()) {
    x = (x << 1) + (x << 3) + (c ^ 48);
  }
  if (flg) {
    x = -x;
  }
  return true;
}
template <class T>
inline void write(T x) {
  if (x < 0) {
    putchar('-');
    x = -x;
  }
  if (x < 10) {
    putchar(x | 48);
    return;
  }
  write(x / 10);
  putchar((x % 10) | 48);
}
const int maxn = 15005;
int n;
struct Edge {
  int to, nxt;
} e[maxn << 1];
int first[maxn];
inline void add_edge(int from, int to) {
  static int cnt = 0;
  e[++cnt].nxt = first[from];
  first[from] = cnt;
  e[cnt].to = to;
  e[++cnt].nxt = first[to];
  first[to] = cnt;
  e[cnt].to = from;
}
long long dpw[maxn];
long long dpn[maxn];
int siz[maxn];
int huan[maxn];
int hs;
int stac[maxn];
int top;
bool vis[maxn];
bool oh[maxn];
inline bool dfsh(int now, int fa) {
  vis[now] = true;
  stac[++top] = now;
  for (int i = first[now]; i; i = e[i].nxt) {
    int to = e[i].to;
    if (to != fa) {
      if (vis[to]) {
        while (stac[top] != to) {
          huan[++hs] = stac[top];
          top--;
        }
        huan[++hs] = to;
        top--;
        return true;
      }
      if (dfsh(to, now)) {
        return true;
      }
    }
  }
  top--;
  return false;
}
inline void dfss(int now, int fa) {
  siz[now] = 1;
  for (int i = first[now]; i; i = e[i].nxt) {
    int to = e[i].to;
    if (!oh[to] && to != fa) {
      dfss(to, now);
      siz[now] += siz[to];
    }
  }
}
inline void dfs1(int now, int fa) {
  dpn[now] = siz[now];
  for (int i = first[now]; i; i = e[i].nxt) {
    int to = e[i].to;
    if (!oh[to] && to != fa) {
      dfs1(to, now);
      dpn[now] += dpn[to];
    }
  }
}
long long dp[maxn][2];
long long xx[maxn];
long long qzh[maxn];
inline long long sum(int l, int r) {
  if (l <= r) {
    return qzh[r] - qzh[l - 1];
  } else {
    swap(l, r);
    l++, r--;
    return qzh[hs] + qzh[l - 1] - qzh[r];
  }
}
inline int pre(int x) {
  if (x == 1) {
    return hs;
  } else {
    return x - 1;
  }
}
inline int nxt(int x) {
  if (x == hs) {
    return 1;
  } else {
    return x + 1;
  }
}
inline void dfsall(int now, int fa) {
  for (int i = first[now]; i; i = e[i].nxt) {
    int to = e[i].to;
    if (!oh[to] && to != fa) {
      dpw[to] = dpw[now] - (n - siz[now]) + dpn[now] - siz[now] - dpn[to];
      dpw[to] += (n - siz[to]) << 1;
      dfsall(to, now);
    }
  }
}
int main() {
  read(n);
  for (int i = 1; i <= n; ++i) {
    int f, t;
    read(f), read(t);
    f++, t++;
    add_edge(f, t);
  }
  dfsh(1, 0);
  for (int i = 1; i <= hs; ++i) {
    oh[huan[i]] = true;
  }
  for (int i = 1; i <= hs; ++i) {
    dfss(huan[i], 0);
    dfs1(huan[i], 0);
  }
  for (int i = 1; i <= hs; ++i) {
    xx[i] = dpn[huan[i]];
    qzh[i] = qzh[i - 1] + siz[huan[i]];
  }
  for (int i = 1; i <= hs; ++i) {
    dp[i][1] = xx[i];
  }
  for (int len = 2; len < hs; ++len) {
    for (int l = 1; l <= hs; ++l) {
      int r = l + len - 2;
      if (r >= hs) {
        r -= hs;
      }
      r++;
      dp[l][len & 1] = max(dp[nxt(l)][~len & 1] + xx[l] + sum(nxt(l), r),
                           dp[l][~len & 1] + xx[r] + sum(l, pre(r)));
    }
  }
  for (int i = 1; i <= hs; ++i) {
    dpw[huan[i]] = dp[nxt(i)][~hs & 1] + n - siz[huan[i]];
    dfsall(huan[i], 0);
  }
  long long ans = 0;
  for (int i = 1; i <= n; ++i) {
    ans = max(ans, dpw[i] + dpn[i]);
  }
  printf("%lld", ans);
  return 0;
}
