基环树
找环,环外处理,环上处理
#include#define re return #define inc(i,l,r) for(int i=l;i<=r;++i) using namespace std; template inline void rd(T&x) { char c;bool f=0; while((c=getchar())<'0'||c>'9')if(c=='-')f=1; x=c^48; while((c=getchar())>='0'&&c<='9')x=x*10+(c^48); if(f)x=-x; } #define ll long long const int maxn=1e6+5; int n,col,k; bool vis[maxn]; int hd[maxn],du[maxn],c[maxn],q[maxn<<1]; ll f[maxn],d[maxn],a[maxn<<1],b[maxn<<1]; struct node{ int to,nt,val; }e[maxn<<1]; inline void add(int x,int y,int z) { e[++k].to=y;e[k].nt=hd[x];hd[x]=k;e[k].val=z;++du[x]; e[++k].to=x;e[k].nt=hd[y];hd[y]=k;e[k].val=z;++du[y]; } inline void dfs(int s,int t) { int l,r,i; q[l=r=1]=s;c[s]=t; while(l<=r) { for(i=hd[q[l]];i;i=e[i].nt) if(!c[e[i].to]) { q[++r]=e[i].to; c[e[i].to]=t; } ++l; } } inline void topsort() { int l=1,r=0,v,m=0; inc(i,1,n) if(du[i]==1)q[++r]=i; while(l<=r) { for(int i=hd[q[l]];i;i=e[i].nt) if(du[v=e[i].to]>1) { d[c[v]]=max(d[c[v]],f[q[l]]+f[v]+e[i].val); f[v]=max(f[v],f[q[l]]+e[i].val); if(--du[v]==1)q[++r]=v; } ++l; } } inline void Get_ans(int t,int x) { if(t==6) t=6; int l=1,r=0,m=0,y=x,i=1,v; while(i) { du[y]=1; for(i=hd[y];i;i=e[i].nt) if(du[v=e[i].to]>1) { y=v; a[++m]=f[v]; b[m]=e[i].val+b[m-1]; break; } } if(m==1) { for(i=hd[y];i;i=e[i].nt) if(e[i].to==x&&e[i].val>b[1]) b[1]=e[i].val; d[t]=max(d[t],f[x]+f[y]+b[1]); re ; } for(i=hd[y];i;i=e[i].nt) if(e[i].to==x) {a[++m]=f[x];b[m]=e[i].val+b[m-1];break;} inc(i,m+1,m*2) a[i]=a[i-m],b[i]=b[i-1]+b[i-m]-b[i-m-1]; q[l=r=1]=1; for(int i=2;i<(m*2);i++) { while(l<=r&&(i-m)>=q[l])++l; d[t]=max(d[t],a[i]+a[q[l]]+b[i]-b[q[l]]); while(l<=r&&a[q[r]]-b[q[r]]<=a[i]-b[i])--r; q[++r]=i; } } int main() { int x,y,z; rd(n); inc(i,1,n) { rd(x),rd(y); add(i,x,y); } inc(i,1,n) if(!c[i])dfs(i,++col); topsort(); ll ans=0; inc(i,1,n) if(du[i]>1&&(!vis[c[i]])) { vis[c[i]]=1; Get_ans(c[i],i); ans+=d[c[i]]; } printf("%lld",ans); re 0; }