题意:
题解:
首先bb一下,本蒟蒻即将被第4个学校的dalao们吊打。
wor,考场上做这道题时接连看错两次题意,简直差点自闭,还好暴力分给得足。
然后吐槽一下题解的玄学程度…如果脸黑的话随机出来的数据真的还跑得过?算了就假设出数据的人没那么非,所有数据中树的深度就是期望深度
=
1
+
∑
i
=
1
n
1
i
=
1
+
ln
n
+
Θ
(
1
)
=1+\displaystyle \sum_{i=1}^n{\dfrac{1}{i}}=1+\ln n+\Theta(1)
=1+i=1∑ni1=1+lnn+Θ(1),子树大小就是期望大小
≤
n
u
\le \dfrac{n}{u}
≤un。证明过程略。其实是我自己太菜了证不来
树形dp是一个很容易想到的方向,但具体怎么实现还是有点恶心。我们很容易想到dp[i][j]为以i为根的子树上亮了j个点的答案。但是状态还要考虑到从1到i的路径上的情况,而如果强行记在状态里面的话存不下,那就一边dfs一边存状态。把所有a[u][v],b[u][v]都加到lca(u,v)上作为u与lca(u,v)之间的点权,然后求出从1到u的状态为s时u的贡献。然后在树上跑个背包即可。
代码:
#include<cstdio>
#include<cstring>
#define maxn 1005
#define D 10
#define INF 0x3f3f3f3f
int n,dp[maxn][maxn],fa[maxn][D],l[maxn][maxn],dep[maxn],siz[maxn],ans,val[maxn][maxn][2],sta[maxn];
struct node { int v; node *nxt; } edge[maxn],*head[maxn],*ncnt;
inline int max(int a,int b) { return a>b?a:b; }
void swap(int &a,int &b) { int t=a; a=b,b=t; }
void addedge(int u,int v)
{
ncnt++;
ncnt->v=v,ncnt->nxt=head[u];
head[u]=ncnt;
}
void dfs1(int u,int d)
{
siz[u]=1,dep[u]=d;
for(node *p=head[u];p;p=p->nxt) { dfs1(p->v,d+1); siz[u]+=siz[p->v]; }
}
int lca(int u,int v)
{
if(dep[u]<dep[v]) swap(u,v);
int t;
for(t=0;(1<<t)<=dep[u];t++); t--;
for(;t>=0;t--)
if(dep[fa[u][t]]>=dep[v]) u=fa[u][t];
if(u==v) return u;
for(t=0;(1<<t)<=dep[u];t++); t--;
for(;t>=0;t--)
if(fa[u][t]!=fa[v][t]) u=fa[u][t],v=fa[v][t];
return fa[u][0];
}
void dfs2(int u,int fa,int d)
{
int tmp[maxn];
for(int i=0;i<=siz[u];i++) dp[u][i]=-INF;
sta[d]=1,dp[u][1]=0;
for(int i=1;i<=d;i++)
if(sta[i]) dp[u][1]+=val[u][i][1];
if(siz[u]>1)
{
dp[u][0]=0;
for(int i=1;i<=d;i++)
if(!sta[i]) dp[u][0]+=val[u][i][0];
}
for(node *p=head[u];p;p=p->nxt)
{
int v=p->v; dfs2(v,u,d+1);
for(int i=siz[u];i>=0;i--)
{
dp[u][i]+=dp[v][0];
for(int j=1;j<=siz[v]&&j<=i;j++) dp[u][i]=max(dp[u][i],dp[u][i-j]+dp[v][j]);
}
}
memcpy(tmp,dp[u],sizeof(dp[u]));
for(int i=0;(i<<1)<siz[u];i++) tmp[i]=-INF;
for(int i=0;i<=siz[u];i++) dp[u][i]=-INF;
sta[d]=0;
if(siz[u]>1)
{
dp[u][1]=0;
for(int i=1;i<=d;i++)
if(sta[i]) dp[u][1]+=val[u][i][1];
}
dp[u][0]=0;
for(int i=1;i<=d;i++)
if(!sta[i]) dp[u][0]+=val[u][i][0];
for(node *p=head[u];p;p=p->nxt)
{
int v=p->v; dfs2(v,u,d+1);
for(int i=siz[u];i>=0;i--)
{
dp[u][i]+=dp[v][0];
for(int j=1;j<=siz[v]&&j<=i;j++) dp[u][i]=max(dp[u][i],dp[u][i-j]+dp[v][j]);
}
}
for(int i=(siz[u]+1)>>1;i<=siz[u];i++) dp[u][i]=-INF;
for(int i=0;i<=siz[u];i++) dp[u][i]=max(dp[u][i],tmp[i]);
}
void read(int &x)
{
char ch=getchar(); int f=1; x=0;
while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if(ch=='-') f=-1,ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+f*(ch-'0');
}
int main()
{
scanf("%d",&n); ncnt=&edge[0];
for(int i=2;i<=n;i++) { read(fa[i][0]); addedge(fa[i][0],i); }
dfs1(1,1);
for(int j=1;j<D;j++)
for(int i=1;i<=n;i++) fa[i][j]=fa[fa[i][j-1]][j-1];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) l[i][j]=l[j][i]=lca(i,j);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i!=j)
{
int a,b;
read(a); read(b);
val[i][dep[l[i][j]]][0]+=a;val[i][dep[l[i][j]]][1]+=b;
}
dfs2(1,0,1);
for(int i=0;i<=n;i++) ans=max(ans,dp[1][i]);
printf("%d\n",ans);
}