/*
* 思路:
* 如果A讨厌B,则连一条B->A的有向边,题目就是要求一个基环树森林上,不共边的点的最大权值和,从环上入手
* 每一棵基环树单独处理,找到基环树上的环,将环的头尾断开,假设尾是Q,头是P,如果将Q到P的边删除,剩下的
* 就是一棵简单的树,在简单的树上做不共线的最大点权值和可以方便用树形DP求解,所以只需要考虑断开的边对求解
* 有什么影响
*
* 设dp(node, 0)表示以节点node为根的子树上,如果node节点不选,最大的权值和
* dp(node, 1)表示以节点node为根的子树上,如果node节点b必选,最大的权值和
* 最后的方案要么选P,要么不选P,如果P点必选,那么Q点就必然不能选,这种情况下,将Q->P边删掉,求解dp(P, 1), 且
* dp求解过程中对Q点特判, 让dp(Q, 1)不参加递推就行了,因为这种状态不满足Q不能选的约束
*
* 如果P点不选,那Q点可选可不选,拆掉Q->P的边,对问题求解无影响,直接求dp(P, 0), 不进行任何特判
*
* 最后两种情况取一个最大值就是答案
*
*/
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int N = 1000005;
const int M = N;
int next_node[N]; // 有向边的下一个点
bool visit[N];
bool processed[N];
int path[N];
int last_pos[N]; // 每一个节点最后一次出现在path中的位置
int path_pos;
int h[N], e[M], w[M], ne[M], idx;
bool rm[M];
long long tot_ans = 0;
inline void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
long long cache1[N][2];
long long cache2[N][2];
void dp(int root, int must_zero, long long ans[][2]) {
long long tot = 0;
for (int e_idx = h[root]; ~e_idx; e_idx = ne[e_idx]) {
if (rm[e_idx]) {
continue;
}
int nei = e[e_idx];
dp(nei, must_zero, ans);
if (nei != must_zero) {
tot += max(ans[nei][0], ans[nei][1]);
} else {
tot += ans[nei][0];
}
}
ans[root][0] = tot;
tot = w[root];
for (int e_idx = h[root]; ~e_idx; e_idx = ne[e_idx]) {
if (rm[e_idx]) {
continue;
}
int nei = e[e_idx];
tot += ans[nei][0];
}
ans[root][1] = tot;
}
long long solve(int start, int end) {
int node2 = path[start], node1 = path[end];
long long ret1, ret2;
dp(node2, node1, cache1);
dp(node2, 0, cache2);
return max(cache1[node2][1], cache2[node2][0]);
}
// dfs找环
void dfs(int cur) {
visit[cur] = 1;
processed[cur] = 1;
path[path_pos++] = cur;
last_pos[cur] = path_pos-1;
for (int e_idx = h[cur]; ~e_idx; e_idx = ne[e_idx]) {
int nei = e[e_idx];
if (visit[nei]) {
rm[e_idx] = true;
long long ret = solve(last_pos[nei], path_pos-1);
tot_ans += ret;
} else {
dfs(nei);
}
}
visit[cur] = 0;
path_pos--;
}
int main(void) {
//freopen("/Users/grh/Programming/CLionProjects/SimpleTest/input.txt", "r", stdin);
int n;
int b;
long long ww;
memset(h, -1, sizeof h);
scanf("%d", &n);
for (int i = 1; i<= n; i++) {
scanf("%lld %d", &ww, &b);
next_node[i] = b;
add(b, i);
w[i] = ww;
}
for (int i = 1; i <= n; i++) {
if (!processed[i]) {
dfs(i);
}
}
printf("%lld\n", tot_ans);
return 0;
}