`圣诞树 `_ ========================================================= 我们可以任选一个点为根节点,进行dfs。 dfs返回的是当前子树的不同color数,我们可以用set去重。 当子树满足size(set) >= k时,我们就把它裁掉,答案加1。 若不满足则启发式合并到我们的set里,最后返回给父节点。 最后判断根节点返回的set的大小即可。 这样贪心能够尽快的裁掉满足条件的部分,为后面腾出更多的color让后面有更对可能会凑齐。 这是一种感性上分析,但具体证明目前本人无能为力。 .. code-block:: cpp #include #define all(a) a.begin(), a.end() #define int long long #define PII pair using ll = long long; const int N = 1e5 + 10, INF = 1e18, MOD = 1e9 + 7; using namespace std; void solve() { int n, k; cin >> n >> k; vector col(n); for (int i = 0; i < n; i++) cin >> col[i]; vector> eg(n); for (int i = 0; i < n - 1; i++) { int u, v; cin >> u >> v; --u, --v; eg[u].push_back(v); eg[v].push_back(u); } int ans = 0; auto dfs = [&](auto &&dfs, int u, int fa) -> set { set s = {col[u]}; for (auto v : eg[u]) { if (v == fa) continue; auto it = dfs(dfs, v, u); if (it.size() >= k) ans++; else { if (s.size() < it.size()) swap(s, it); for (auto x : it) s.insert(x); } } return s; }; auto it = dfs(dfs, 0, -1); cout << ans + (it.size() >= k) << "\n"; } signed main() { ios::sync_with_stdio(0), cin.tie(0); int T = 1; // cin >> T, cin.get(); while (T--) solve(); return 0; }