1. 程式人生 > >【BZOJ】ARC083 E - Bichrome Tree

【BZOJ】ARC083 E - Bichrome Tree

cst 多少 style aps 樹型dp mem 個數 opened spl

【算法】樹型DP

【題意】給定含n個點的樹的形態,和n個數字Xv,要求給每個點賦予黑色或白色和權值,滿足對於每個點v,子樹v中和v同色的點的權值和等於Xv

【題解】首先每個點的權值可以任意大,那麽v的子樹(不含v的部分)權值多少就無所謂了(因為缺的可以由v來補足),但是太大的話超過Xv就不可行了。

也就是說對於一個點v,假定其為黑色,那麽子樹中黑色總和為Xv,白色總和就要最小,將其定義為f[v]。

技術分享
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cctype>
using
namespace std; const int maxM=5010,maxn=1010,inf=0x3f3f3f3f; int f[maxn],g[2][maxM],n,first[maxn],tot,v[maxn]; struct edge{int v,from;}e[maxn]; int read(){ char c;int s=0,t=1; while(!isdigit(c=getchar()))if(c==-)t=-1; do{s=s*10+c-0;}while(isdigit(c=getchar())); return s*t; } void insert(int
u,int v){tot++;e[tot].v=v;e[tot].from=first[u];first[u]=tot;} int min(int a,int b){return a<b?a:b;} void dfs(int x){ for(int i=first[x];i;i=e[i].from)dfs(e[i].v); memset(g[0],0x3f,sizeof(g[0])); int X=0; g[X][0]=0; for(int i=first[x];i;i=e[i].from){ int y=e[i].v; X=1
-X; memset(g[X],0x3f,sizeof(g[X])); for(int j=0;j<=v[x];j++){ if(j-v[y]>=0)g[X][j]=min(g[X][j],g[1-X][j-v[y]]+f[y]); if(j-f[y]>=0)g[X][j]=min(g[X][j],g[1-X][j-f[y]]+v[y]); } } for(int i=0;i<=v[x];i++)f[x]=min(f[x],g[X][i]); } int main(){ n=read(); for(int i=2;i<=n;i++){ int p=read(); insert(p,i); } for(int i=1;i<=n;i++)v[i]=read(); memset(f,0x3f,sizeof(f)); dfs(1); if(f[1]<inf)printf("POSSIBLE");else printf("IMPOSSIBLE"); return 0; }
View Code

【BZOJ】ARC083 E - Bichrome Tree