#include<bits/stdc++.h>
using namespace std;
long long n,SUM;
struct island
{
long long to,len,rudu,maxx1,maxx2;
}is[3000006];
struct HUAN
{
long long len,sta,sum;
}huan[3000005];
long long h,Huan[3000005],Bian[3000005],H;
struct QQQQQ
{
long long sum,i;
};
long long head[6000006],to[6000006],num[6000006],len[6000006],tot;
bool visit[3000006];
long long f[3000006];
long long ans;
void add_edge(long long x,long long y,long long k)
{
tot++;
len[tot]=k;
num[tot]=y;
to[tot]=head[x];
head[x]=tot;
}
long long dfs(long long p)
{
for(long long i=head[p];i;i=to[i])
{
if(!visit[num[i]] && is[num[i]].rudu==1)
{
visit[num[i]]=true;
Huan[++H]=num[i];
Bian[H]=len[i];
huan[h].len++;
huan[h].sum+=len[i];
return dfs(num[i]);
}
else
{
if(visit[num[i]] && is[num[i]].rudu==1)
{
huan[h].sum+=len[i];
return len[i];
}
}
}
}
int main()
{
ios::sync_with_stdio(0);cin.tie(0);
cin>>n;
for(long long i=1;i<=n;i++)
{
cin>>is[i].to>>is[i].len;
add_edge(i,is[i].to,is[i].len);
is[is[i].to].rudu++;
}
queue<long long> Q;
for(long long i=1;i<=n;i++)
{
if(is[i].rudu==0)
{
Q.push(i);
}
}
while(!Q.empty())
{
long long p=Q.front();
Q.pop();
for(long long i=head[p];i;i=to[i])
{
is[num[i]].rudu--;
if(len[i]+is[i].maxx1>is[num[i]].maxx1)
{
is[num[i]].maxx2=is[num[i]].maxx1;
is[num[i]].maxx1=len[i]+is[i].maxx1;
}
else if(len[i]+is[i].maxx1>is[num[i]].maxx2)is[num[i]].maxx2=len[i]+is[i].maxx1;
if(is[num[i]].rudu==0)
{
Q.push(num[i]);
}
}
}
for(long long i=1;i<=n;i++)
{
visit[i]=false;
}
for(long long i=1;i<=n;i++)
{
if(is[num[i]].rudu==1 && !visit[num[i]])
{
huan[++h].sta=H+1;
huan[h].len++;
visit[num[i]]=true;
Huan[++H]=num[i];
Bian[H]=dfs(num[i]);
}
}
queue<QQQQQ> m1,m2;//m1:i-disi,m2:i+disi
QQQQQ PUT;
for(long long i=1;i<=h;i++)
{
for(long long j=huan[i].sta;j<=huan[i].len+huan[i].sta-1;j++)
{
ans=max(ans,is[Huan[j]].maxx1+is[Huan[j]].maxx2);
}
PUT.sum=is[Huan[huan[i].sta]].maxx1;
PUT.i=1;
m1.push(PUT);
m2.push(PUT);
for(long long j=2;j<huan[i].len*2;j++)
{
long long I=(((j-1)%huan[i].len+1)-1)+huan[i].sta;
if(I-huan[i].sta+1==1)f[I]=f[huan[i].sta+huan[i].len-1]+Bian[I];
else f[I]=f[I-1]+Bian[I];
while(!m1.empty() && ((j-m1.front().i>=huan[i].len)))
{
m1.pop();
}
long long Front1=m1.front().sum;
ans=max(ans,is[Huan[I]].maxx1+f[I]+Front1);
while(!m1.empty() && ((m1.front().sum)<=is[Huan[I]].maxx1-f[I]))
{
m1.pop();
}
PUT.sum=is[Huan[I]].maxx1-f[I];
PUT.i=j;
m1.push(PUT);
while(!m2.empty() && ((j-m2.front().i>=huan[i].len)))
{
m2.pop();
}
long long Front2=m2.front().sum;
ans=max(ans,is[Huan[I]].maxx1-f[I]+Front2+huan[i].sum);
while(!m2.empty() && ((m2.front().sum)<=is[Huan[I]].maxx1+f[I]))
{
m2.pop();
}
PUT.sum=is[Huan[I]].maxx1+f[I];
PUT.i=j;
m2.push(PUT);
}
while(!m1.empty())
{
m1.pop();
}
while(!m2.empty())
{
m2.pop();
}
SUM+=ans;
ans=0;
}
cout<<SUM;
return 0;
}
具体思路是先处理每个环上的点的子树最大值和第二大值,然后在环上dp,分别处理每个环,最后累加答案