题解
考虑哪一些点可以变为相邻的儿子节点,
就是某个点以及它的右链,和这个点父亲的下一个儿子以及它的左链,这里面的点都可两两相互成为相邻的叶子节点。
于是就开始dp,
设
表示最后一个叶子节点在i的时候是最大值,
考虑如何转移,
很显然,先找出两条链来,这个过程类似求lca的过程。
然后维护一个前缀,
讨论新构成的链的最大值在哪一条链上面。
code
#include <iostream>
#include <algorithm>
#include <cstring>
#include<cstdio>
#include <string.h>
#include <cmath>
#include <math.h>
#define ll long long
#define N 1000003
#define P putchar
#define G getchar
using namespace std;
char ch;
void read(int &n)
{
n=0;
ch=G();
while((ch<'0' || ch>'9') && ch!='-')ch=G();
ll w=1;
if(ch=='-')w=-1,ch=G();
while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
n*=w;
}
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
ll abs(ll x){return x<0?-x:x;}
ll sqr(ll x){return x*x;}
void write(ll x){if(x>9) write(x/10);P(x%10+'0');}
int lst[N],nxt[N],to[N],tot;
int son[N],v[N],f[N],g[N],fa[N],id,n,m;
int now,dfn[N],dep[N],ans,q[N],x,y,mx[N];
int d1[N],d2[N],t1,t2;
void ins(int x,int y)
{
fa[y]=x;
nxt[++tot]=lst[x];
to[tot]=y;
lst[x]=tot;
}
void dfs(int x)
{
dfn[++now]=x;dep[x]=dep[fa[x]]+1;
for(int i=lst[x];i;i=nxt[i])
dfs(to[i]),son[x]=1;
if(!son[x])q[++q[0]]=x;
}
int main()
{
freopen("temmie.in","r",stdin);
freopen("temmie.out","w",stdout);
read(n);
for(int i=1;i<=n;i++)
{
read(v[i]);read(m);
for(int j=1;j<=m;j++)read(x),ins(i,x);
}
memset(son,0,sizeof(son));
dfs(1);
for(x=q[1];x;x=fa[x])f[x]=v[x];
for(int i=2;i<=q[0];i++)
{
t1=t2=0;
for(x=q[i-1],y=q[i];dep[x]>dep[y];x=fa[x])d1[++t1]=x;
for(;dep[x]<dep[y];y=fa[y])d2[++t2]=y;
for(;x!=y;x=fa[x],y=fa[y])d1[++t1]=x,d2[++t2]=y;
g[0]=mx[t1+1]=-2147473647;
for(int i=t1;i;i--)mx[i]=max(mx[i+1],v[fa[d1[i]]]);
for(int i=1;i<=t1;i++)g[i]=max(g[i-1],f[d1[i]]-mx[i]);
id=t1;x=y=-1000000000;
for(int i=t2;i;i--)
{
x=max(x,v[fa[d2[i]]]);
for(;id && x>mx[id];id--)y=max(y,f[d1[id]]);
f[d2[i]]=max(y-x,g[id])+v[d2[i]];
}
}
for(x=dfn[n];x;x=fa[x])ans=max(ans,f[x]);
printf("%d",ans);
return 0;
}