#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
#define INF int(1e9)
using namespace std;
typedef long long LL;
const int N = 1e6 + 10, M = N << 1;
int n;
int h[N], e[M], ne[M], w[M], idx;
int deg[N];
vector<int> vers;
bool vis[N];
int num; // 表示 环上 一共有几个点
LL f[N], d[N]; // f[u] 表示以u为根的最长直径 d[u] 表示以u为根的最长链
LL res;
int q[N << 1], l, r; // 单调队列 指针
LL a[N << 1], sum[N << 1];
void add(int a,int b,int c){
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}
// bfs 出 x 的连通块
void bfs(int x){
// 清空全局 数组
vers.clear();
queue<int> q;
q.push(x);
vis[x] = true;
while(q.size()){
int t = q.front(); q.pop();
vers.push_back(t);
for(int i = h[t];~i;i = ne[i]){
int j = e[i];
if(vis[j]) continue;
vis[j] = true;
q.push(j);
}
}
}
void topsort(){
queue<int> q;
for(int &ver : vers){
if(deg[ver] == 1)
q.push(ver);
vis[ver] = false;
}
// for(int i = 0;i < vers.size();i ++ ){
// if(deg[vers[i]] == 1) q.push(vers[i]);
// vis[vers[i]] = false;
// }
while(q.size()){
int t = q.front(); q.pop();
vis[t] = true;
for(int i = h[t];~i;i = ne[i]){
int j = e[i];
if(vis[j]) continue;
// 先更新 f 再更新 d: 防止直径是重边回路
// 以 j 为根的子树 中的直径 1.过根2.不过根
f[j] = max(f[j], f[t]);
f[j] = max(f[j], d[j] + d[t] + w[i]);
// 更新 d
d[j] = max(d[j], d[t] + w[i]);
if( -- deg[j] == 1) q.push(j);
}
}
num = 0;
// for (int i = 0; i < vers.size();i ++ ){
// if(vis[vers[i]]) continue;
// vers[num ++ ] = vers[i];
// }
for(int &ver : vers){
if(!vis[ver]) vers[num ++ ] = ver;
}
}
LL solve(){
// 当前节点 上一个边
int p = vers[0], last = 0, n = 0;
res = 0;
// 把整个环找出来 并update res
do{
for(int i = h[p];~i;i = ne[i]){
int j = e[i];
if(i == last) continue;
if(vis[j]) continue;
last = i ^ 1 ,p = j;
res = max(res, f[p]);
a[n] = d[p];
sum[n ++ ] = w[i];
vis[p] = true;
break;
}
}while(p != vers[0]);
memcpy(a + num, a, num * sizeof(LL));
memcpy(sum + num, sum, num * sizeof(LL));
// 经过环的res res = max(res, a[i] + a[j] + sum[j] - sum[i]); (i < j)
// 其实就是 在 j 前面找一个 i 使得 max(a[i] - sum[i]) 用一个单调队列(单调递减)
l = 0, r = -1;
// 求前缀和
for(int i = 1;i < 2 * num;i ++ )
sum[i] += sum[i - 1];
for(int j = 0;j < 2 * num;j ++ ){
// update l
while(l <= r && j - q[l] >= num)
l ++ ;
// update res
if(l <= r) res = max(res, a[q[l]] + a[j] + sum[j] - sum[q[l]]);
// update r
while(l <= r && a[j] - sum[j] >= a[q[r]] - sum[q[r]])
r -- ;
q[ ++ r] = j;
}
return res;
}
int main(){
scanf("%d", &n);
memset(h, -1, sizeof h);
for(int i = 1;i <= n;i ++ ){
// y 表示下一个点 z 表示边权
int y, z; scanf("%d%d", &y, &z);
add(i, y, z), add(y, i, z);
deg[i] ++ , deg[y] ++ ;
}
LL res = 0;
for(int i = 1;i <= n;i ++ ){
if(vis[i]) continue;
bfs(i); // bfs 之后就得到了一个连通块
topsort(); // topsort 找环
res += solve();
}
printf("%lld\n", res);
return 0;
}