sol:
考虑对于每个基环树求答案。
对于一棵树,考虑对于每个点只保留通向它的最大的边。
对于基环树,考虑强行断掉环上的一条边,记录环上点通向它的最大边和次大边,如果最大边都是环上边就必须选择一个点强行断成非环边。
注意特判所有点形成一个环的情况。
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define fi first
#define se second
#define db double
using namespace std;
const int Maxn=1e5+5;
int n,m,p[Maxn],cnt,cnt2,a[Maxn],b[Maxn],suf[Maxn],in[Maxn],hua[Maxn],vis[Maxn];
ll tot,res,mx[Maxn],mx2[Maxn];
int head,tail,q[Maxn];
ll loop(int rt) {
int f=0;
ll tmp=inf,tmp2=0;
m=0;
p[++m]=rt;
for(int i=a[rt];i!=rt;i=a[i]) {
p[++m]=i;
}
for(int i=1;i<=m;i++) {
tmp2+=mx[p[i]];
vis[p[i]]=1;
if(mx[p[i]]>mx2[p[i]]&&suf[p[i]]==mx[p[i]]) {
tmp=min(tmp,mx[p[i]]-mx2[p[i]]);
}
else {
f=1;
}
}
if(f==1) {
return tmp2;
}
else {
return tmp2-tmp;
}
}
signed main() {
scanf("%d",&n);
for(int i=1;i<=n;i++) {
scanf("%d%d",&a[i],&b[i]);
tot+=b[i];
in[a[i]]++;
if(b[i]>mx[a[i]]) {
mx2[a[i]]=mx[a[i]];
mx[a[i]]=b[i];
}
else if(b[i]>mx2[a[i]]) {
mx2[a[i]]=b[i];
}
}
for(int i=1;i<=n;i++) hua[i]=1;
head=1;
for(int i=1;i<=n;i++) {
if(in[i]==0) {
q[++tail]=i;
}
}
while(head<=tail) {
int x=q[head++];
hua[x]=0;
if(--in[a[x]]==0) q[++tail]=a[x];
}
for(int i=1;i<=n;i++) {
if(hua[i]) {
suf[a[i]]=b[i];
}
}
for(int i=1;i<=n;i++) {
if(hua[i]&&!vis[i]) {
res+=loop(i);
cnt++;
}
else if(!hua[i]) {
cnt2++;
res+=mx[i];
}
}
if(cnt==1&&cnt2==0) {
printf("0");
return 0;
}
printf("%lld",tot-res);
}