結果
| 問題 | No.3769 Even Contraction |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2026-10-05 10:49:23 |
| 言語 | C++17 (gcc 15.3.0 + boost 1.92.0 + ACL) |
| 結果 |
AC
不安定
|
| 実行時間 | 41 ms / 2,000 ms |
| + 624µs | |
| コード長 | 2,201 bytes |
| 記録 | |
| コンパイル時間 | 1,518 ms |
| コンパイル使用メモリ | 222,524 KB |
| 実行使用メモリ | 13,600 KB |
| 最終ジャッジ日時 | 2026-10-16 20:57:49 |
| 合計ジャッジ時間 | 6,406 ms |
|
ジャッジサーバーID (参考情報) |
judge1_0 / judge5_0 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 47 |
ソースコード
/// Opus 5.5
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<vector<int>> 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<int> a(n);
for (int i = 0; i < n; i++) cin >> a[i];
// BFS 順(再帰を使わない)
vector<int> 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<long long> 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;
}