三校聯考20181024T2 點亮light
阿新 • • 發佈:2018-12-17
題意:
題解:
首先bb一下,本蒟蒻即將被第4個學校的dalao們吊打。
wor,考場上做這道題時接連看錯兩次題意,簡直差點自閉,還好暴力分給得足。
然後吐槽一下題解的玄學程度…如果臉黑的話隨機出來的資料真的還跑得過?算了就假設出資料的人沒那麼非,所有資料中樹的深度就是期望深度,子樹大小就是期望大小。證明過程略。其實是我自己太菜了證不來
程式碼:
#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);
}