本来今天想学基环树的
认真看一看,这不就是弱化的仙人掌嘛
然后,就直接仙人掌上DP咯(蒟蒻不是很会调了一晚上。。。)
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; struct node { int x,y,next; }a[2100000];int len,last[1100000]; void ins(int x,int y) { len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } LL ft[1100000],f[2][1100000]; int z,dfn[1100000],fa[1100000]; bool v[1100000];//是否在仙人掌中 void DP(int rt,int x)//只需要更新rt { LL g[2][2]; int pre=0,now=1; g[now][0]=g[now][1]=0; for(int i=x;i!=rt;i=fa[i]) { swap(pre,now); g[now][0]=max(g[pre][0],g[pre][1])+f[0][i]; g[now][1]=g[pre][0]+f[1][i]; } f[0][rt]+=max(g[now][0],g[now][1]); //不取rt pre=0,now=1; g[now][0]=g[now][1]=0; for(int i=x;i!=rt;i=fa[i]) { swap(pre,now); g[now][0]=max(g[pre][0],g[pre][1])+f[0][i]; if(i==x||fa[i]==rt)g[now][1]=0; else g[now][1]=g[pre][0]+f[1][i]; } f[1][rt]+=max(g[now][0],g[now][1]); //取rt } int h[1100000]; void cactus(int x) { dfn[x]=++z; f[0][x]=0;f[1][x]=ft[x]; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(dfn[y]==0) fa[y]=x, cactus(y); } for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(fa[x]!=y) { if(dfn[y]<dfn[x]) { h[y]=x; for(int i=x;i!=y;i=fa[i])v[i]=true; } else if(v[y]==false) { f[0][x]+=max(f[0][y],f[1][y]); f[1][x]+=f[0][y]; } } } if(h[x]!=-1)DP(x,h[x]); } //------------------------------- int hate[1100000]; int main() { int n,x; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%lld%d",&ft[i],&x); hate[i]=x; if(hate[x]!=i) ins(i,x), ins(x,i); } LL ans=0; memset(dfn,0,sizeof(dfn)); memset(v,false,sizeof(v)); memset(h,-1,sizeof(h)); for(int i=1;i<=n;i++) if(dfn[i]==0) { cactus(i); ans+=max(f[0][i],f[1][i]); } printf("%lld ",ans); return 0; }