题意:
分析:
期望深度logN级。。。
居然还真能把这个视为状压的大小。。。。要是运气稍微好一点不就T完了吗。。。
什么叫实践之后发现并不会T啊。。。
见识了。。。还有这种恶心题。。。
有了这个性质DP起来就很水了。。直接枚举祖先的状态即可。但直接枚举存不下,所以用类似01DFS的方法来搞。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#define SF scanf
#define PF printf
#define MAXN 1010
#define INF 0x3FFFFFFF
using namespace std;
int lca[MAXN][MAXN];
int a[MAXN][MAXN],b[MAXN][MAXN];
int p[MAXN],dep1[MAXN],tot[MAXN];
vector<int> son[MAXN];
int n;
vector<int> cost[MAXN][2];
void dfs(int x){
if(x!=1)
dep1[x]=dep1[p[x]]+1;
tot[x]=1;
for(int i=0;i<int(son[x].size());i++){
dfs(son[x][i]);
tot[x]+=tot[son[x][i]];
}
}
int get_lca(int u,int v){
if(dep1[u]>dep1[v])
swap(u,v);
while(dep1[v]>dep1[u])
v=p[v];
while(u!=v){
u=p[u];
v=p[v];
}
return u;
}
int dp[MAXN][MAXN];
void solve(int x,int dep,int mask){
for(int i=0;i<=tot[x];i++)
dp[x][i]=-INF;
dp[x][0]=cost[x][0][(1<<(dep+1))-1-(mask|(1<<dep))];
dp[x][1]=cost[x][1][mask|(1<<dep)];
int nowsum=1;
for(int i=0;i<int(son[x].size());i++){
int u=son[x][i];
solve(u,dep+1,mask|(1<<dep));
nowsum+=tot[u];
for(int j=nowsum;j>=0;j--){
dp[x][j]+=dp[u][0];
for(int k=min(j,tot[u]);k>=1;k--)
dp[x][j]=max(dp[x][j],dp[x][j-k]+dp[u][k]);
}
}
int maxv=(tot[x]+1)/2;
for(int j=0;j<maxv;j++)
dp[x][j]=-INF;
nowsum=1;
dp[x][0]=cost[x][0][(1<<(dep+1))-1-mask];
if(maxv>1)
dp[x][1]=cost[x][1][mask];
for(int i=0;i<int(son[x].size());i++){
int u=son[x][i];
solve(u,dep+1,mask);
nowsum+=tot[u];
for(int j=min(maxv-1,nowsum);j>=0;j--){
dp[x][j]+=dp[u][0];
for(int k=min(j,tot[u]);k>=1;k--)
dp[x][j]=max(dp[x][j],dp[x][j-k]+dp[u][k]);
}
}
// PF("%d %d:\n",x,mask);
// for(int i=0;i<=tot[x];i++)
// PF("[%d]",dp[x][i]);
// PF("\n");
}
int main(){
freopen("light.in","r",stdin);
freopen("light.out","w",stdout);
SF("%d",&n);
for(int i=2;i<=n;i++){
SF("%d",&p[i]);
son[p[i]].push_back(i);
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
if(i==j)
continue;
SF("%d%d",&a[i][j],&b[i][j]);
}
dfs(1);
for(int i=1;i<=n;i++){
cost[i][0].resize(1<<(dep1[i]+1));
cost[i][1].resize(1<<(dep1[i]+1));
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
if(i==j)
continue;
lca[i][j]=get_lca(i,j);
cost[i][0][1<<dep1[lca[i][j]]]+=a[i][j];
cost[i][1][1<<dep1[lca[i][j]]]+=b[i][j];
// PF("[%d %d %d %d]\n",i,1<<dep1[lca[i][j]],a[i][j],b[i][j]);
}
for(int i=1;i<=n;i++)
for(int j=0;j<(1<<(dep1[i]+1));j++){
int k=j&(-j);
if(cost[i][0][j]==0)
cost[i][0][j]=cost[i][0][j-k]+cost[i][0][k];
if(cost[i][1][j]==0)
cost[i][1][j]=cost[i][1][j-k]+cost[i][1][k];
}
// for(int i=1;i<=n;i++)
// for(int j=1;j<(1<<(dep1[i]+1));j++)
// PF("[%d %d - %d %d]\n",i,j,cost[i][j][0],cost[i][j][1]);
solve(1,0,0);
int res=-INF;
for(int i=0;i<=n;i++)
res=max(res,dp[1][i]);
PF("%d",res);
}