对拍了好久也没找出错误来,球球啦
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#define ll long long
using namespace std;
inline ll read(){
ll f=1,x=0;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=x*10+c-'0';
c=getchar();
}
return f*x;
}
struct edge{
ll nxt,v;
ll val;
}e[2500001];
ll n,tot=1,head[2000001],rd[2000001],d[2000001],q[2000001],cnt=0,father[2000001],hhead=0,tail=0;
ll ssum[2000001],dis[2000001];
bool vis[2000001],vis1[2000001],vis2[2000001];
pair<ll,ll> que[2000001];
inline ll getfather(ll x){
if(father[x]==x) return x;
return father[x]=getfather(father[x]);
}
inline void add(ll u,ll v,ll val){
e[++tot].v=v,e[tot].val=val,e[tot].nxt=head[u],head[u]=tot;
e[++tot].v=u,e[tot].val=val,e[tot].nxt=head[v],head[v]=tot;
}
inline ll dfs(ll now,ll fa,ll top){//求子树
ll d1=0,d2=0;
for(ll i=head[now];i;i=e[i].nxt){
ll to=e[i].v;
if(to==fa||!vis[to]) continue;
ll t=dfs(to,now,top)+e[i].val;
if(t>d1){
d2=d1,d1=t;
}else if(t>d2) d2=t;
}
d[top]=max(d[top],d1+d2);
return d1;
}
inline void dfs1(ll now,ll fa,ll top){//取出环
q[++cnt]=now;
for(ll i=head[now];i;i=e[i].nxt){
ll to=e[i].v;
if(vis[to]||to==fa) continue;
if(to==top){
dis[cnt+1]=dis[cnt]+e[i].val;
break;
}
dis[cnt+1]=dis[cnt]+e[i].val;
dfs1(to,now,top);
break;
}
}
inline void dfs2(ll top){//求环上一个点的所有子树直径最大值
for(ll i=head[top];i;i=e[i].nxt){
int to=e[i].v;
if(!vis[to]) continue;
d[top]=max(d[top],dfs(to,top,to)+e[i].val);
}
}
int main(){
freopen("3.in","r",stdin);
n=read();
for(ll i=1;i<=n;i++) father[i]=i,ssum[i]=1;
for(ll i=1;i<=n;i++){
ll v,val;
v=read(),val=read();
add(i,v,val);
ll f1=getfather(i),f2=getfather(v);
if(f1!=f2) father[f1]=f2,ssum[f2]+=ssum[f1];
rd[i]++,rd[v]++;
}
queue<ll> qq;
for(ll i=1;i<=n;i++){
if(rd[i]==1){
qq.push(i);
}
}
while(!qq.empty()){//拓扑排序找环
ll u=qq.front();
qq.pop();
vis[u]=1;
for(ll i=head[u];i;i=e[i].nxt){
ll to=e[i].v;
rd[to]--;
if(rd[to]==1){
qq.push(to);
}
}
}
for(ll i=1;i<=n;i++){
if(!vis[i]){
dfs2(i);
}
}
ll sum=0;
for(ll i=1;i<=n;i++){
if(!vis[i]&&!vis1[getfather(i)]&&rd[i]>1){
que[0]=que[1]=que[2]=make_pair(0,0);
cnt=0;
vis1[getfather(i)]=1;
if(ssum[getfather(i)]==2){ //特判环大小为2的情况(应该没有问题)
ll al,temp;
cnt=1;
q[1]=i;
for(ll j=head[i];j;j=e[j].nxt){
ll to=e[j].v;
if(!vis[to]){
temp=to;
al=j;
q[2]=to,q[3]=i,q[4]=to;
dis[cnt+1]=dis[cnt]+e[j].val;cnt++;
break;
}
}
for(ll j=head[temp];j;j=e[j].nxt){
ll to=e[j].v;
if(!vis[to]&&j!=(al^1)){
dis[cnt+1]=dis[cnt]+e[j].val;
break;
}
}
dis[cnt+2]=dis[cnt+1]+dis[cnt]-dis[cnt-1];
}else{
dfs1(i,i,i);
for(ll j=cnt+1;j<=2*cnt;j++){//把序列增长一倍
q[j]=q[j-cnt];
if(j>cnt+1) dis[j]=dis[j-1]+dis[j-cnt]-dis[j-cnt-1];
}
}
hhead=tail=1;
ll ans=0;
for(ll j=1;j<=2*cnt;j++){//单调队列求答案
while(hhead<=tail&&que[hhead].second<=j-cnt) hhead++;
ans=max(ans,d[q[j]]+dis[j]+que[hhead].first);
ll temp=d[q[j]]-dis[j];
while(hhead<=tail&&temp>que[tail].first) tail--;
que[++tail]=make_pair(temp,j);
}
sum+=ans;
}
}
cout<<sum;
return 0;
}