/// Opus 5.5 #include using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; vector> g(n); for (int i = 0; i < n - 1; i++) { int u, v; cin >> u >> v; --u; --v; g[u].push_back(v); g[v].push_back(u); } vector a(n); for (int i = 0; i < n; i++) cin >> a[i]; // BFS 順(再帰を使わない) vector par(n, -1), order; order.reserve(n); par[0] = 0; order.push_back(0); for (int i = 0; i < (int)order.size(); i++) { int v = order[i]; for (int c : g[v]) { if (par[c] == -1) { par[c] = v; order.push_back(c); } } } const long long NEG = LLONG_MIN / 4; // P: 純ブロック, U: 未完成ドミノ, S: 完成ドミノ, O: 値1の頂点 vector P(n, NEG), U(n, NEG), S(n, NEG), O(n, NEG); for (int i = n - 1; i >= 0; i--) { int v = order[i]; long long sumP = 0, sumU = 0, sumO = 0, best = NEG; for (int c : g[v]) { if (c == par[v]) continue; long long cl = max({P[c], S[c], O[c]}); // 辺 (v,c) を切る long long pc = max(S[c], O[c]) + 1; // c を別ピースとしてつなぐ if (a[v] == 1) { sumO += max(cl, pc); continue; } long long keepP = (a[c] == a[v]) ? P[c] + 1 : NEG; sumP += max(cl, keepP); long long joinU = (a[c] == a[v]) ? U[c] + 1 : NEG; long long h = max({cl, pc, joinU}); sumU += h; long long sat = NEG; // c を「ドミノを完成させる子」にする場合 if (a[c] == 2 - a[v]) sat = max(sat, U[c] + 1); if (a[c] == a[v]) sat = max(sat, S[c] + 1); if (sat >= 0) best = max(best, sat - h); } if (a[v] == 1) { O[v] = sumO; } else { P[v] = sumP; U[v] = sumU; if (best != NEG) S[v] = sumU + best; } } cout << max({P[0], S[0], O[0]}) << '\n'; return 0; }