现在在 ACWing 上面剩下3个点没过了,这里配上新代码:(更改了代码中dp找树直径的部分),错的点仍然是15 18,答案偏小
#include<bits/stdc++.h>
using namespace std;
#define int long long
typedef long long ll;
const int N=1e6+10;
ll sum[N<<1],val[N];
int head[N],tot,n,m;
struct E{int nxt,to,dis;}e[N<<1];
int st[N],top,vis[N],num,cir[N<<1],cnt;
inline int Max(int x,int y){return x>y?x:y;}
vector<int>Cir[N];
void Get(int node,int x){
int i;
for(i=top;i&&st[i]!=x;--i)Cir[node].push_back(st[i]),st[i]=0;
Cir[node].push_back(x);st[i]=0;
}
void Find_Circle(int x,int fa,int node){
vis[x]=1;st[++top]=x;
for(int i=head[x];i;i=e[i].nxt){
int j=e[i].to;
if(j==fa){continue;}
if(vis[j]&&Cir[node].empty()){Get(node,j);}
if(!vis[j])Find_Circle(j,x,node);
}
--top;
}
inline void link(int u,int v,int w){
e[++tot]=(E){head[u],v,w};
head[u]=tot;
}
#define gc() getchar()
inline int read(){
int s=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch)){
s=s*10+ch-'0';
ch=gc();
}
return s;
}
ll ans=-1;
ll f[N],g[N];
void Dp(int x,int fa,int P){
for(int i=head[x];i;i=e[i].nxt){
int j=e[i].to;
if(j==fa)continue;
if(vis[j])continue;
Dp(j,x,P);
g[P]=Max(g[P],f[x]+f[j]+e[i].dis);
f[x]=Max(f[x],f[j]+e[i].dis);
}
}
int getval(int x,int v){
for(int i=head[x];i;i=e[i].nxt){
int j=e[i].to;
if(j==v)return e[i].dis;
}
return -1;
}
int q[N<<1],tail,Head;
ll dp[N<<1];
void solve(int pos,ll &R){
tail=0;Head=1;
q[++tail]=1;dp[1]=val[cir[1]];
for(int i=1;i<=cnt;++i)cir[i+cnt]=cir[i];
cnt<<=1;
for(int i=2;i<=cnt;++i){
int v=getval(cir[i-1],cir[i]);
sum[i]=sum[i-1]+v;
}
for(int i=2;i<=cnt;++i){
while(Head<=tail&&q[Head]<=i-(cnt/2)+1)++Head;
dp[i]=val[cir[i]]+sum[i]-sum[q[Head]]+val[cir[q[Head]]];
while(Head<=tail&&val[cir[i]]-sum[i]>=val[cir[q[tail]]]-sum[q[tail]])--tail;
q[++tail]=i;
}
ll T=-1;
for(int i=1;i<=cnt;++i)T=Max(T,dp[i]);
R+=T;
for(int i=1;i<=cnt;++i)sum[i]=0;
for(int i=1;i<=cnt;++i)q[i]=0;
}
struct EEE{
int u,v,w;
}Edge[N];
inline bool cmp(EEE x,EEE y){
if(x.u==y.u&&x.v==y.v)return x.w>y.w;
return x.u==y.u?x.v<y.v:x.u<y.u;
}
signed main(){
freopen("in.txt","r",stdin);
// freopen("358.out","w",stdout);
n=read();
for(int i=1;i<=n;++i){
int a=read(),L=read();
int u=i,v=a;
if(u>v)swap(u,v);
Edge[i]=(EEE){u,v,L};
}
sort(Edge+1,Edge+n+1,cmp);
for(int i=1;i<=n;++i){
int u=Edge[i].u;
int v=Edge[i].v;
if(u==Edge[i-1].u&&v==Edge[i-1].v)continue;
link(u,v,Edge[i].w);
link(v,u,Edge[i].w);
}
for(int i=1;i<=n;++i){
if(!vis[i]){
++num;
top=0;
Find_Circle(i,0,num);
if(Cir[num].empty())Cir[num].push_back(i);
}
}
for(int i=1;i<=n;++i)vis[i]=0;
for(int i=1;i<=num;++i)
for(auto v:Cir[i])
vis[v]=1;
for(int i=1;i<=n;++i){
if(!vis[i])continue;
Dp(i,0,i);
val[i]=f[i];
}
// for(int i=1;i<=n;++i)if(vis[i])printf("(%d %lld %lld):\n",i,f[i],g[i]);
ll Res=0;
for(int i=1;i<=num;++i){
ll mx=-1;
for(auto v:Cir[i])mx=Max(mx,g[v]);
Res+=mx;
}
ans=Max(Res,ans);
ll res=0;
for(int i=1;i<=num;++i){
int L=Cir[i].size();
top=0;
if(L<=1){
ll mx=-1;
for(auto v:Cir[i])mx=Max(mx,g[v]);
res+=mx;
continue;
}
cnt=0;
for(auto v:Cir[i])cir[++cnt]=v;
solve(i,res);
}
ans=Max(ans,res);
printf("%lld\n",ans);
return 0;
}