Bichrome Tree 树形DP⭐
6611: Bichrome Tree
时间限制: 1 Sec 内存限制: 128 MB
提交: 222 解决: 63
[提交] [状态] [讨论版] [命题人:admin]
题目描述
We have a tree with N vertices. Vertex 1 is the root of the tree, and the parent of Vertex i (2≤i≤N) is Vertex Pi.
To each vertex in the tree, Snuke will allocate a color, either black or white, and a non-negative integer weight.
Snuke has a favorite integer sequence, X1,X2,…,XN, so he wants to allocate colors and weights so that the following condition is satisfied for all v.
The total weight of the vertices with the same color as v among the vertices contained in the subtree whose root is v, is Xv.
Here, the subtree whose root is v is the tree consisting of Vertex v and all of its descendants.
Determine whether it is possible to allocate colors and weights in this way.
Constraints
1≤N≤1 000
1≤Pi≤i−1
0≤Xi≤5 000
输入
Input is given from Standard Input in the following format:
N
P2 P3 … PN
X1 X2 … XN
输出
If it is possible to allocate colors and weights to the vertices so that the condition is satisfied, print POSSIBLE; otherwise, print IMPOSSIBLE.
样例输入
3 1 1 4 3 2
样例输出
POSSIBLE
提示
For example, the following allocation satisfies the condition:
Set the color of Vertex 1 to white and its weight to 2.
Set the color of Vertex 2 to black and its weight to 3.
Set the color of Vertex 3 to white and its weight to 2.
There are also other possible allocations.
题意:给一棵树上每个点分配权值和颜色,颜色包括黑白两色,问是否有可能使每个点及其子树中相同颜色的点的权值相加等于x[i]
假设当前节点u为黑色,因为该节点权值可以无限大,所以尽量求得其子树中白色的权值的最小值,这样之后计算其他子树白色权值时才能小于x[i],设f[u]为当前节点u的子树中与u的颜色不同的点的权值之和
当u为黑色时,其子树中v
若v与u同色,v的权值和x[v]加入u中,计算是否超过x[u]
若不同色,则将f[v]加入,计算是否超过x[u]
代码:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
const int maxx=1e5+100;
const int MOD=1e9;
struct node
{
int to,nextt;
}e[maxx];
int n;
int p[maxx];
int x[maxx];
int head[maxx];
int dp[maxx];
int f[maxx];
int cnt=0;
void add(int u,int v)
{
e[cnt].to=v;
e[cnt].nextt=head[u];
head[u]=cnt++;
}
void dfs(int u)
{
for(int i=head[u]; ~i; i=e[i].nextt){
dfs(e[i].to);
}
dp[0]=0;
for(int i=head[u]; ~i; i=e[i].nextt){
int v=e[i].to;
for(int j=x[u]; j>=0; j--){
int temp=INF;
if(j>=x[v])
temp=min(temp,dp[j-x[v]]+f[v]);
if(j>=f[v])
temp=min(temp,dp[j-f[v]]+x[v]);
dp[j]=temp;
}
}
for(int i=0; i<=x[u]; i++){
f[u]=min(f[u],dp[i]);
}
}
int main()
{
scanf("%d",&n);
memset(head,-1,sizeof(head));
for(int i=2; i<=n; i++){
scanf("%d",&p[i]);
add(p[i],i);
}
for(int i=1; i<=n; i++){
scanf("%d",&x[i]);
}
memset(f,INF,sizeof(f));
dfs(1);
if(f[1]<INF)
cout<<"POSSIBLE"<<endl;
else
cout<<"IMPOSSIBLE"<<endl;
return 0;
}