Problem:
Score : 700 points

Problem Statement

We have a tree with N vertices. Vertex 1 is the root of the tree, and the parent of Vertex i (2 \leq i \leq N) is Vertex P_i.

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, X_1, X_2, ..., X_N, 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 X_v.

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 \leq N \leq 1 000

1 \leq P_i \leq i - 1

0 \leq X_i \leq 5 000

Inputs

Input is given from Standard Input in the following format:

N
P_2 P_3 ... P_N
X_1 X_2 ... X_N

Outputs

If it is possible to allocate colors and weights to the vertices so that the condition is satisfied, print POSSIBLE; otherwise, print IMPOSSIBLE.

Sample Input 1

3
1 1
4 3 2

Sample Output 1

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.

Sample Input 2

3
1 2
1 2 3

Sample Output 2

IMPOSSIBLE

If the same color is allocated to Vertex 2 and Vertex 3, Vertex 2 cannot be allocated a non-negative weight.

If different colors are allocated to Vertex 2 and 3, no matter which color is allocated to Vertex 1, it cannot be allocated a non-negative weight.

Thus, there exists no allocation of colors and weights that satisfies the condition.

Sample Input 3

8
1 1 1 3 4 5 5
4 1 6 2 2 1 3 3

Sample Output 3

POSSIBLE

Sample Input 4

1

0

Sample Output 4

POSSIBLE

Solution in C++ (GCC 9.2.1) (judge verdict: Wrong Answer)

#include <bits/stdc++.h>
#include <cassert>
#define rep(i, n) for (int i = 0; i < (n); i++)
using namespace std;
using ll = long long;
using P = pair<int, int>;
struct Edge
{
  int to;
  int weight;
  Edge(int t, int w) : to(t), weight(w) {}
};
// using Graph = vector<vector<Edge>>;
using Graph = vector<vector<int>>;

const long long INF = 1LL << 60;
const int INT_INF = 1000000000;

int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
// int dx[8] = {-1, -1, -1, 0, 0, 1, 1, 1}, dy[8] = {-1, 0, 1, 1, -1, 1, 0, -1};

void dfs(Graph &G, vector<vector<ll>> &dp, vector<int> &X, int v, int p)
{
  int white = 0, black = 0;
  vector<int> any;
  for (auto u : G[v])
  {
    if (u == p)
      continue;
    dfs(G, dp, X, u, v);

    // どっちもだめはだめ
    if (dp[u][0] == INF && dp[u][1] == INF)
    {
      // cout << "IMPOSSIBLE" << endl;
      return;
    }

    if (dp[u][0] == INF)
    {
      // 子供は1(黒)しかなれない
      white = dp[u][1];
      black = X[u];
    }
    else if (dp[u][1] == INF)
    {
      // 子供は0(白)しかなれない
      white = X[u];
      black = dp[u][1];
    }
    else
    {
      any.push_back(u);
    }
  }

  // whiteをblack最小で作る
  vector<ll> dp2(5050, INF);
  dp2[white] = black;
  for (auto ch : any)
  {
    vector<ll> pd2(5050, INF);
    for (int i = 5000; i >= 0; i--)
    {
      if (dp2[i] != INF)
      {
        // white採用
        if (i + X[ch] < 5050)
        {
          pd2[i + X[ch]] = min(pd2[i + X[ch]], dp2[i] + dp[ch][1]);
        }
        if (i + dp[ch][0] < 5050)
          pd2[i + dp[ch][0]] = min(pd2[i + dp[ch][0]], dp2[i] + X[ch]);
      }
    }
    swap(dp2, pd2);
  }

  for (int i = 0; i < X[v] + 1; i++)
  {
    if (dp2[i] != INF)
      dp[v][0] = min(dp[v][0], dp2[i]);
  }

  // 逆
  dp2.resize(5050, INF);
  dp2[black] = INF;
  for (auto ch : any)
  {
    vector<ll> pd2(5050, INF);
    for (int i = 5000; i >= 0; i--)
    {
      if (dp2[i] != INF)
      {
        if (i + X[ch] < 5050)
          pd2[i + X[ch]] = min(pd2[i + X[ch]], dp2[i] + dp[ch][0]);
        if (i + dp[ch][1] < 5050)
          pd2[i + dp[ch][0]] = min(pd2[i + dp[ch][1]], dp2[i] + X[ch]);
      }
    }
    swap(dp2, pd2);
  }
  for (int i = 0; i < X[v] + 1; i++)
  {
    if (dp2[i] != INF)
      dp[v][1] = min(dp[v][1], dp2[i]);
  }
}

int main()
{
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int N;
  cin >> N;
  Graph G(N);
  for (int i = 1; i < N; i++)
  {
    int P;
    cin >> P;
    P--;
    G[i].push_back(P);
    G[P].push_back(i);
  }
  vector<int> X(N);
  for (auto &it : X)
    cin >> it;
  vector<vector<ll>> dp(N + 1, vector<ll>(2, INF));

  dfs(G, dp, X, 0, -1);

  if (dp[0][0] == INF && dp[0][1] == INF)
    cout << "IMPOSSIBLE" << endl;
  else
    cout << "POSSIBLE" << endl;

  return 0;
}

// 木DPをする．dp[cu][white=0|black=1]:=頂点cuがwhite|blackであるときに頂点cuの部分木で逆の色に書いてある数の総和の最小値
// 各頂点で白にでも黒にでも出来る子供があった場合は更にDPをして考える．