圣诞树§

我们可以任选一个点为根节点,进行dfs。

dfs返回的是当前子树的不同color数,我们可以用set去重。

当子树满足size(set) >= k时,我们就把它裁掉,答案加1。

若不满足则启发式合并到我们的set里,最后返回给父节点。

最后判断根节点返回的set的大小即可。

这样贪心能够尽快的裁掉满足条件的部分,为后面腾出更多的color让后面有更对可能会凑齐。

这是一种感性上分析,但具体证明目前本人无能为力。

#include <bits/stdc++.h>
#define all(a) a.begin(), a.end()
#define int long long
#define PII pair<int, int>
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<int> col(n);

    for (int i = 0; i < n; i++)
        cin >> col[i];

    vector<vector<int>> 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<int>
    {
        set<int> 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;
}